论坛首页 Java企业应用论坛

JNI不完全指南

浏览 2381 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-12   最后修改:2009-02-12

JNI不完全指南

1.      概述

JNI做为对JVM的补充,可以完成一些游离于JVM之外的代码,完成一些OS严重依赖的功能,比如你想自己实现基于IMCPping(如果问为什么,那么请重新学习一下IP/TCP/Socket)

JNI包括Java代码和Native代码,所谓的native代码并非说一定是C的,即使你用其它的语言实现也可以,但是需要把它包装成操作系统特定的库,JRE中会有专门的代码去利用操作系统接口去动态加载它。

实现JNI的主体步骤如下:

1)        完成Java代码

2)        完成native代码

3)        封装native代码到系统库

4)        使用native

2.      Step By Step样例

我们一步一步来实现一个基于Sun JDKJNI的例子。其中,native代码用C来实现。而最终,这个JNI的例子将分别被部署到windowslinux上,两者有小小的区别将在后面说明。

l  Java

在需要使用native方法的类中,加上native的声明,然后像abstract方法一样不必给出实现。

package demo;

public class HelloWorld {

    final static String name = "laurence";

public static String getName(){

   return name;

}

    public native String sayHello(String msg);

}

很普通的Java类,注意其中的阴影部分。

l  C

分为两部分

1)         生成native代码的头文件

2)         实现native代码

生成native头文件

javah -classpath target/classes -d . demo.HelloWorld

target/classes是指定当前目录下的target/classes目录为classpathdemo.HelloWorldclass文件就在这下面

-d指输出头文件的目录,这里设为当前了

demo.HelloWorld是包含了native方法声明的Java类名

 

完成javah命令之后,会输出一个头文件,在本例中是demo_HelloWorld.h,代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class demo_HelloWorld */

 

#ifndef _Included_demo_HelloWorld

#define _Included_demo_HelloWorld

#ifdef __cplusplus

extern "C" {

#endif

    /*

     * Class:     demo_HelloWorld

     * Method:    sayHello

     * Signature: (Ljava/lang/String;)Ljava/lang/String;

     */

    JNIEXPORT jstring JNICALL Java_demo_HelloWorld_sayHello

    (JNIEnv *, jobject, jstring);

 

#ifdef __cplusplus

}

#endif

#endif

实现native代码

C实现demo_HelloWorld.c,代码如下:

#include "demo_HelloWorld.h"

#include <time.h>

 

JNIEXPORT jstring JNICALL Java_demo_HelloWorld_sayHello(JNIEnv* env,

       jobject method, jstring param) {

    char buf[1025];

    const char *pt = (*env)->GetStringUTFChars(env, param, NULL);

    time_t now;

    time(&now);

    strcpy(buf, pt);

    strcat(buf, asctime(localtime(&now)));

    return (*env)->NewStringUTF(env, buf);

}

这个方法做的事情就是读取参数param,在后面加上个时间戳并返回新的字符串。

简单解释一下其中的关键行代码。

GetStringUTFCharsjre中提供的jni方法,用来得到java string的字符串。

NewStringUTFjre中提供的jni方法,用来新建java string

具体的jni方法,请参考sunjni帮助文档和样例。

l  操作系统相关

对于不同的操作系统,都有系统相关的库封装方式。在Linux上是Shared Object(.so文件),在Windows上就是Dynamic Load Library(.dll文件),其它不常用的请自行解决吧。

Linux

不需要额外的工作,直接编译成Shared Object即可。

一条指令全搞定:

gcc  -Wall -m32 -fPIC -I/usr/java5/include  -I/usr/java5/include/linux  -Wl,-melf_i386  -shared  -lc  -Wl,--soname=hello <s

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics