Jni入门
参考:
JNI 开发流程 - JNI/NDK 开发指南 - 极客学院Wiki
1、编写native方法,使用javah创建头文件
1 | public class HelloWorld { |
1 | javah -jni -classpath JniCalcINterface |
参数说明:
classpath:类搜索路径,这里表示从当前的 bin 目录下查找
d:将生成的头文件放到当前的 jni 目录下
o: 指定生成的头文件名称,默认以类全路径名生成(包名+类名.h)
注意:-d和-o只能使用其中一个参数。
创建的.h文件如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/* DO NOT EDIT THIS FILE - it is machine generated */
/* Header for class com_study_jnilearn_HelloWorld */
extern "C" {
/*
* Class: com_study_jnilearn_HelloWorld
* Method: sayHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello
(JNIEnv *, jclass, jstring);
}
**注意 extern “C”表示兼容C语言,当调用C编写的.h头文件或者函数的时候,一定要写在extern “C”后面
3、编译出so文件
1 | gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -shared HelloWorld.c -o libHelloWorld.so |
参数含义:
-L
- 表示要链接的库所在的目录。-L. 表示要链接的库在当前目录, -L/usr/lib 表示要连接的库在/usr/lib下。目录在/usr/lib时,系统会自动搜索这个目录,可以不用指明。
-l (L的小写)
- 表示需要链接库的名称,注意不是库文件名称,比如库文件为 libtest.so,那么库名称为test
-include
- 包含头文件,这个很少用,因为一般情况下在源码中,都有指定头文件。
-I (i 的大写)
- 指定头文件的所在的目录,可以使用相对路径。
-shared
- 指定生成动态链接库
-fPIC
- 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码共享的目的。
-o
- 指定编译后动态库生成的路径和文件名
4、加载动态库
1 | static{ |
方式1:只需要指定动态库的名字即可,不需要加lib前缀,也不要加.so、.dll和.jnilib后缀
方式2:指定动态库的绝对路径名,需要加上前缀和后缀 推荐使用这种方法
如果使用方式1,java 会去 java.library.path 系统属性指定的目录下查找动态库文件,如果没有找到会抛出java.lang.UnsatisfiedLinkError异常。
有两种方式可以让 Java 从 java.library.path 找到动态链接库文件,聪明的你应该已经想到了。
将动态链接库拷贝到java.library.path目录下, linux可以拷贝到/usr/local/lib目录下
给 jvm 添加“-Djava.library.path=动态链接库搜索目录”参数,指定系统属性 java.library.path 的值 java -Djava.library.path=/Users/yangxin/Desktop Linux/Unix 环境下可以通过设置 LD_LIBRARY_PATH 环境变量,指定库的搜索目录。