我这几天需要在Linux进行java开发,需要用到jni技术,在网上找了一些资料,现在还在开发过程中,下面的文章在开发过程中根据自己的实际应用也做了一下修改,先做一个笔记.
本文转至http://www.cnblogs.com/hanyuanbo/archive/2012/07/10/2584758.html
主要参考资料为《JAVA核心技术 II:高级特性》这本书第十二章,不过网上也有些关于介绍如何做相关工作的,由于项目需要使用Java来调用c代码,所以需要生成so库这样来使用,过程中遇到了一些问题,特此分享下。
做so文件主要分为一下几步:
- 编写.java文件,其中有声明native方法
- javac生成.class文件
- javah生成.h文件
- 编写.c文件
- gcc打成so文件
- 将so库文件放到-Djava.library.path目录下
- 使用so库文件
下面就如何写一个so动态库并正确使用的HelloNative的过程,其中可能遇到的问题,我也会注明。
- Linux下用Eclipse新建一个工程,暂命名为HelloNative,新建一个HelloNative.java的类,内容截图如 图1.
- 如果是Eclipse工程下的话class文件是自动生成的,也可以自己生成,内容截图如图2.
- javah生成需要的.h文件,这个过程中人为的指定下-classpath最好,这样没有问题,这样找到了class文件,注意所在的路径。不过需要注意的是,需要加入包的名称,否则可能会遇到UnsatisfiedLinkError错误,本人没有尝试不加包的编译情况,如图3.
- 编写.c文件来调用.h文件并实现其中的方法,如图4. (函数是从.h文件拷贝过来的,不过参数要加上变量,否则编译会出现问题。)
- 使用命令来生成so库文件,g++ -fPIC -I /usr/lib/jvm/java-8-oracle/include/ -I /usr/lib/jvm/java-8-oracle/include/linux/ -shared -o libftd2xxdriver.so ./jni/com_sim_ttydemo_NativeClass.cpp -lpthread libftd2xx.a ,如图5.
- (1)我是新建了一个lib文件夹将so文件放到了其中,然后在Eclipse的vm argument中指定即可,即-Djava.library.path=lib。这个可以很多种方式,只要程序能找到即可。如图6.;(2)还有另外一种方式也可以调用到我们编写的.so文件,这样做就不用像(1)中那样加载so:
static {
System.load("/home/swan/test/libgoodluck.so");
} - 编写文件来使用这个库文件。注意这个加载库文件的操作需要在原来那个HelloNative中加载,否则会出现UnsatisfiedLinkError错误,这也是图1为什么我注释掉那个橙色部分代码的原因,在编写native的生成文件时不需要加载,但是在使用的时候需要HelloNative.java去加载,只要取消注释即可,然后在Eclipse的VM Argument中指定-Djava.library.path=lib即可,然后编写HelloNativeTest文件进行调用,如图7.
至此完成最最基本的so文件编写调用过程,更加复杂的比如参数传递、访问域等的操作请参照《JAVA核心技术 II:高级特性》第十二章。
图1
图2
图3
图4
图5
图6
图7