通过JNI实现Java对C/C++的调用
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
大致步骤
编写带有native声明的方法的java类
使用javac命令编译所编写的java类
使用javah命令生成扩展名为h的头文件
使用C/C++实现本地方法
将C/C++编写的文件生成动态连接库
1) 编写java程序:
1 2 3 4 5 6 7 8 9 10 11 12 | public class HelloNative{ public native void greeting();//所有native所修饰的都是本地方法 static{System.loadLibrary("HelloNative");//载入本地库 } public static void main(String[] args){new HelloNative().greeting();// System.out.println(System.getProperty("java.library.path")); }} |
声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明该方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。 Load动态库:System.loadLibrary(“HelloNative”);加载动态库(我们可以这样理解:我们的方法 greeting()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary();的参数“HelloNative”是动态库的名字。
2) 编译
1 | javac HelloNative.java |
3) 生成扩展名为h的头文件
1 | javah HelloNative |
命令执行后会在当前目录下生产一个c的头文件,名字为HelloNative.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 */#include <jni.h>/* Header for class HelloNative */ #ifndef _Included_HelloNative#define _Included_HelloNative#ifdef __cplusplusextern "C" {#endif/* * Class: HelloNative * Method: greeting * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloNative_greeting (JNIEnv *, jobject); #ifdef __cplusplus}#endif#endif |
这个h文件相当于我们在java里面的接口,这里声明了一个 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我们的本地方法里面实现这个方法,也就是说我们在编写C/C++程序的时候所使用的方法名必须和这里的一致
4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。
1 2 3 4 5 6 7 8 9 | #include <stdio.h>#include <jni.h>#include "HelloNative.h" JNIEXPORT void JNICALL Java_HelloNative_greeting (JNIEnv * env, jobject obj){ printf("Hello, Native!\n");} |
5) 生成动态库
1 | gcc -fPIC -I/home/elton/jdk/include -I/home/elton/jdk/include/linux -shared -o libHelloNative.so HelloNative.c |
注意,必须告知编译器jni.h所在的接口位置。linux的动态库都是以lib开头,以.so结尾的,要遵守这个命名规范。-fPIC是告诉编译器生成跟位置无关的动态链接库
命令执行后,会在当前目录生成一个libHelloNative.so的动态链接库文件
6) 运行程序
1 | java -Djava.library.path=. HelloNative |
必须指定java.library.path变量的内容,告诉java你的动态链接库的位置。
或者在命令行上输入
1 | export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH |
这样就不用每次调试的时候都输入-Djava.library.path=.这个参数了。
当你部署的时候,你通过System.out.println(System.getProperty(“java.library.path”));得到你系统的java.library.path位置,然后把你的动态链接库拷贝到这个目录中。我用的是ubuntu 11.04 64位版本,得到的结果是
1 | /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib |
这样你的动态链接库就永远都会被java访问到了,不用每次指定环境变量了。
建议继续学习:
- Java技术路线 (阅读:6862)
- Java应用运维 (阅读:3751)
- Java陷阱(2010版) (阅读:3239)
- Java将Object对象转换为String的总结合集 (阅读:2936)
- Java 常量值修改后不起作用 (阅读:2795)
- Java的那些事儿 (阅读:2757)
- Eclipse Xtend对Java说:我帮你瘦身 (阅读:2632)
- Java泛型简明教程 (阅读:2628)
- 如何在Hadoop集群运行jni程序 (阅读:2263)
- 五四陈透过PHP看JAVA系列:strtotime (阅读:2265)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Elton 来源: Elton's Blog
- 标签: Java JNI
- 发布时间:2011-07-30 21:25:17
- [46] 界面设计速成
- [43] 视觉调整-设计师 vs. 逻辑
- [43] Oracle MTS模式下 进程地址与会话信
- [42] IOS安全–浅谈关于IOS加固的几种方法
- [42] android 开发入门
- [39] 图书馆的世界纪录
- [38] 程序员技术练级攻略
- [38] 【社会化设计】自我(self)部分――欢迎区
- [38] 如何拿下简短的域名
- [34] 读书笔记-壹百度:百度十年千倍的29条法则