Linux 下 Java JNI 调用 .so 文件的方法
刚刚试过一个这样的例子,省事起见,略改并记录如下:
1. Java 类编写
public class Hello {
static {
System.loadLibrary("goodluck");
}
public static native int get();
public static native void set(int i, String s);
public static void main(String[] args) {
try {
Hello test = new Hello();
test.set(10, "5555");
System.out.println(test.get());
} catch (Exception ex) {
System.out.println("ssssss");
}
}
}
OK Java 类有了。
执行:
javac Hello.java
上面成功后,再执行下面生成头文件:
javah Hello
生成了 Hello.h
2. C 语言实现
编写 Hello.c:
#include "Hello.h"
int i = 0;
JNIEXPORT jint JNICALL Java_Hello_get(JNIEnv *env, jclass jc) {
return i;
}
JNIEXPORT void JNICALL Java_Hello_set(JNIEnv *env, jclass jc, jint j, jstring s) {
char *tsetstr = (char *)(*env)->GetStringUTFChars(env, s, NULL); // 注意此处 jstring 和 char *的转换
printf("%s--------\n", tsetstr);
i = j;
}
保存,然后执行如下编译指令:
gcc -fPIC -D_REENTRANT -I/usr/java/jdk1.6.0_31/include -I/usr/java/jdk1.6.0_31/include/linux -c Hello.c
gcc -shared Hello.o -o libgoodluck.so
此时就生成了 libgoodluck.so。
注意为了让 Java 找到此 so,运行:
export LD_LIBRARY_PATH=.
将当前目录(so 文件目录,不包括文件名)加入此环境变量。
然后运行 java Hello,屏幕上打出了 10。
然后测试下传入 String 型的参数,对应的 JNI 定义应为 jstring,但却出了些问题,在显示结果时仿佛内存溢出的样子。
后来查了查,需对 jstring 和 char *作一个转换,如代码中所示,然后结果就正常。
补充说明
- 将编写的 Hello.c 文件编译成 .o 文件:
gcc -fPIC -D_REENTRANT -I/usr/lib/jvm/java-1.5.0-sun-1.5.0.19/include -I/usr/lib/jvm/java-1.5.0-sun-1.5.0.19/include/linux -c Hello.c
注:/usr/lib/jvm/java-1.5.0-sun-1.5.0.19/include 是 jni.h 头文件所在的路径,/usr/lib/jvm/java-1.5.0-sun-1.5.0.19/include/linux 是 jni_md.h 所在的路径。
- 将生成的 Hello.o 文件编译成 .so 库文件:
gcc -shared Hello.o -o libgoodluck.so
注: 和 Windows 下不同,Linux 的库文件必须是以 libxxx.so 形式命名的(或者 libxxx.so.y,y 是版本号),lib 前缀是为了系统能够识别它,xxx 是 Java 代码 System.loadLibrary("xxx"); 中引用库的名字。
将生成的 libgoodluck.so 文件拷贝到 Java 的加载库 LD_LIBRARY_PATH 指向的路径中。 前提是你有足够的权限,如果没有 sudo 权限的同学,用下面的方法:
- 在 /home 下建立一个用来存放 .so 库文件的目录,比如 ./jni_lib
- 把 libgoodluck.so 文件拷贝到该目录下
- 打开 Terminal,运行如下命令:
export LD_LIBRARY_PATH=./jni_lib
只在当前 shell 下有效...
另外, 以下方法可以直接利用绝对路径来 load 这个 so 库文件,从而无需做上述的放置 path 或者更改库路径的动作:
static { System.load("./jni_lib/libgoodluck.so"); }
