JNI的一个简单实例

本例子使用的操作系统MacOS, 64位JVM。

 

JNI编写的几个步骤如下:

 

编写Java代码,并注明native方法:

 

public class HelloJni {

    public native void displayHelloJni();

    public static void main(String[] args) {
        HelloJni helloJni = new HelloJni();
        helloJni.displayHelloJni();
    }

    static {
        System.loadLibrary("HelloJniImpl");
    }
}

 

其中声明displayHelloJni()方法为本地方法,在static静态块中用System.loadLibrary()加载本地库。

 

使用javac命令编译此java类:

 

javac com/xxx/clamaa/jni/HelloJni.java 

  

 

利用javah命令生成C语言的头文件(.h文件)

 

javah com.xxx.clamaa.jni.HelloJni

 

 

执行完成后,就在执行路径下生成名称为com_xxx_clamaa_jni_HelloJni.h的头文件:

 

#include <jni.h>
/* Header for class com_xxx_clamaa_jni_HelloJni */

#ifndef _Included_com_xxx_clamaa_jni_HelloJni
#define _Included_com_xxx_clamaa_jni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_yonyou_clamaa_jni_HelloJni
 * Method:    displayHelloJni
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_xxx_clamaa_jni_HelloJni_displayHelloJni
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 

 

然后在同级的目录下新建一个HelloJniImpl.cpp文件,这个与HelloJni.java中定义的System.loadLibrary()的文件名一致。

 

 

#include "com_xxx_clamaa_jni_HelloJni.h"
#include <iostream>
#include <jni.h>
using namespace std;
/*
 * Class:     HelloWorld
 * Method:    displayHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_xxx_clamaa_jni_HelloJni_displayHelloJni
  (JNIEnv *, jobject)
 {
    cout << "Hello Jni by clamaa!";
    return;
}

 

编译C++代码的时候在MacOS下和在Linux Windows有所不同, 不是编译成.so或者dll, 而是MacOS自己的jnilib. 并且jni.h的目录也比较特殊, 是/System/Library/Frameworks/JavaVM.framework/Headers/,执行的命令g++,

g++ -dynamiclib -o libhellojniimpl.jnilib HelloJniImpl.cpp -framework JavaVM -I/System/Library/Frameworks/JavaVM.framework/Headers

 

编译完成后,就生成libhellojniimpl.jnilib文件,此时执行结果为:

java com.xxx.clamaa.jni.HelloJni
>Hello Jni by clamaa!

 

生成的文件名称必须为: libhellojniimpl.jnilib,否则抛出异常:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloJniImpl in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1119)
	at com.yonyou.clamaa.jni.HelloJni.<clinit>(HelloJni.java:16)

 

如果设置成带参数的本地方法,那么生成的参数会多一个jstring

Java_HelloWorld_print(JNIEnv *env, jobject obj, jstring str)

 

与原来的实现方式,调用方式都一样,这样简单的JNI实现就完成了。 

 

 如果我们在原来的cpp实现中加入一行抛出异常的代码:

cout << "Hello Jni by clamaa!";
throw 1;
return;

 

那么在执行的过程中也会抛出对应的错误:

java com.yonyou.clamaa.jni.HelloJni
>libc++abi.dylib: terminating with uncaught exception of type int
>Hello Jni by clamaa!Abort trap: 6

 

 

posted @ 2014-09-16 21:43  clamaa  阅读(247)  评论(0编辑  收藏  举报