当HelloJNI类加载的时候,静态初始化调用 System.loadLibrary() 来加载本地库 hello.dll(或libhello.so)。如果不能加载 hello 库,会抛出 UnsatisfiedLinkError 异常。
然后我们使用 native 关键字声明了 native 方法 sayHello() ,这表明该方法是使用其它语言实现的。
最后 main() 方法实例化了 HelloJNI 并调用了 sayHello().
然后我们编译这个类:
使用 javah 创建头文件:
会得到如下 .h 文件 HelloJNI.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class HelloJNI */ #ifndef _Included_HelloJNI #define _Included_HelloJNI #ifdef __cplusplus extern "C" { #endif /* * Class: HelloJNI * Method: sayHello * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif |
这份自动生成的头文件里声明一个 C 函数 Java_HelloJNI_sayHello:
|
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jobject); |
这个方法名是由javah转换来的,转换规则为:
|
Java_{package_and_classname}_{function_name}(JNI arguments) |
包名中的 点 会被转换为 下划线
函数中带有两个参数(虽然我们在本例中并没有使用这两个参数)
- JNIEnv*: 指向 JNI environment ,提供对 JNI 方法的访问
- jobject: 指向 this Java 对象
2.1.3 C 代码的实现
HelloJNI.c
|
#include <jni.h> #include <stdio.h> #include "HelloJNI.h" JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv * env, jobject obj) { printf("Hello World!"); } |
这个实现将在控制台打印万能的 "Hello World!"
文件中包含了 jni.h 头文件。这个头文件由 java 提供,位于 %JAVA_HOME%/include 路径下(Windows下还需要引用 %JAVA_HOME%/include/win32).
2.1.4 编译 C 库
接下来,编译这个 c 文件:
|
#Windows gcc > gcc -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o hello.dll HelloJNI.c #Windows VS cl.exe link.exe > cl /c /I%JAVA_HOME%/include /I%JAVA_HOME%/include/win32 HelloJNI.c > link HelloJNI.obj /DLL /OUT:hello.dll |
2.1.5 检查成果
继续阅读