Java虽然强大,但对于面向底层的一些操作还是略显不足,此时唯有通过JNI来进行调用本地方法来扩展Java程序的功能。可以将native方法类比为Java中声明的接口方法,然后在外部用其他语言进行实现。
其实现步骤如下:
1、在Java中声明native()方法,然后编译;
2、用javah产生一个.h文件;
3、写一个.c或.cpp文件实现native导出方法,其中需要include第二步产生的.h文件,另根据需要可以自己再include其他文件;
4、将第三步的.c或.cpp文件编译成动态链接库文件(这个不同的系统下操作方法不同);
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
显然,如题所说,网络上关于Windows下JNI的使用多如牛毛,这里我就只说一下Linux(我用的是Ubuntu10.04)下的JNI调用。
1.先编写一个Java文件,这里我保存为文件名Test.java
public class Test {
//此处定义的便是native方法
native public void doSomeThing();
public static void main (String args[]) {
Test test = new Test();
test.doSomeThing();
}
static{
//这个作何用处下面的步骤会作说明
System.loadLibrary("libtest");
}
}
之后进行编译(javac)生成Test.class文件
2.通过javah -jni Test,会生成一个Test.h的头文件,其内容如下
#include <jni.h>
#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_Test_doSomeThing
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3接着我再编写一个Test.c文件来进行
#include <stdio.h>
#include "Test.h" //这里要包含刚才生成的头文件
JNIEXPORT void JNICALL Java_Test_doSomeThing(JNIEnv * name, jobject o)
{
printf("HelloWorld");
return;
}
4将Test.c编译成动态链接库,下面是其命令
gcc -shared -I /usr/lib/jvm/java-6-sun-1.6.0.20/include -I /usr/lib/jvm/java-6-sun-1.6.0.20/include/linux -I /usr/include Test.c -o libtest.so
解释一下上面的操作,当然我的系统是Ubuntu10.04,不过关于jdk安装之后的路径应该大同小异,自己做下适当的调整即可
/usr/lib/jvm/java-6-sun-1.6.0.20/include下包含的jni.h
/usr/lib/jvm/java-6-sun-1.6.0.20/include/linux下包含的是jni-mid.h
-shared 是设置生成share object的标志
libtest.so即为我们需要的动态链接库(等同于Windows下的*.dll文件)。
5.可以再看Test.java中 System.loadLibrary("libtest");的作用了,就是让其加载libtest而已。
顺便说明一下,用static声明的域不需要用try..catch来捕获异常,否则还是捕获一下为好。
OK,现在大功告成,让我们来运行该程序即可
java -Djava.library.path=. Test
输出结果就是...还是你自己试下吧
本文参考了http://www.linux.com/community/blogs/simple-jni-on-ubuntu-904.html,同时可参见我翻译的中文网址http://arescaiser.iteye.com/blog/804636
额,我先是在OpenOffice上完成的,选择的是微软雅黑的字体,只是没想到JavaEye不支持这个,所以造成了格式乱码,现在已经改过来了,给大家造成不便敬请谅解