在java中,有时候我们不得不要去使用其他语言的代码,比如说:
1、你的应用需要访问系统的各个特性和设备,这些特性和设备通过java平台是无法访问的。
2、你已经有了大量的测试过和调试过的用另一种语言编写的代码,并且知道如何将其导出到所有的目标平台上。
3、通过基础测试,你已经发现所编写的java代码比用其他语言编写的等价代码要慢得多。
java平台有一个用于和本地c代码进行互操作的api,称为java本地接口(jni)。现在就开始学习jni,先从这篇的一个最简单的例子,了解如何使用jni调用本地方法。
调用本地方法,打印出helloworld的步骤示例
1、在类中声明一个本地方法
1
2
3
4
|
package com.tao.test; public class nativetest { public static native void sayhello(); } |
我们使用native关键字,声明了一个本地方法,而且我们还将他声明为static。本地方法可以是静态的,也可以不声明为静态的。
2、编译.java文件,生成 含有该本地方法的类的字节码
如果是在eclipse中,进入<工程目录>\bin\com\tao\test,就可以找到eclipse自动为我们编译的.class文件。
如果不是,则进入进入nativetest.java文件所在的目录,使用javac命令编译该java类,生成了nativetest.class字节码。
3、使用javah命令编译.class字节码,生成包含native方法声明的c/c++头文件
如果是在eclipse中,进入<工程目录>\bin目录,然后使用下面的编译命令(如果不是eclipse,则根据上面编译生成的.class文件的位置来用javap编译)
1.javah com.tao.test.nativetest //记住要使用类型的全限定名称
就会在bin目录下,生成我们需要的c\c++头文件 com_tao_test_nativetest.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 com_tao_test_nativetest */ #ifndef _included_com_tao_test_nativetest #define _included_com_tao_test_nativetest #ifdef __cplusplus extern "c" { #endif /* * class: com_tao_test_nativetest * method: sayhello * signature: ()v */ jniexport void jnicall java_com_tao_test_nativetest_sayhello (jnienv *, jobject); #ifdef __cplusplus } #endif #endif |
4、按照生成的c/c++头文件来写c/c++源文件,并编译为dll动态链接库
我们之前得到了包含native方法声明的c/c++头文件,现在我们按照这个头文件,编写我们的c\c++源文件,并编译为dll动态链接库。
上一步,我们得到了com_tao_test_nativetest.h头文件。
①、首先。新建一个win32 dll项目(我使用的是vs2005开发环境,vc6.0++是新建一个win32 dynamic-link library)
新建——>项目——>visual c++——>win32——>控制台应用程序——>输入项目名称,我使用为nativecall
点击确定后,进入下面的界面
点击下一步,进入下一界面,勾选为dll和空项目。
这样就建立了一个win32 dll项目了。
②、添加com_tao_test_nativetest.h头文件
将com_tao_test_nativetest.h头文件复制,黏贴到nativecall/nativecall/目录下,如e:\vcproject\nativecall\nativecall该文件夹。然后再vs2005中的项目中,添加该头文件
③、添加jni.h和
打开com_tao_test_nativetest.h头文件,看第二行,调用了 jni.h,这个头文件需要我们自己添加,为了java_home/include目录下,添加方式和第②步一样
1
2
3
4
5
|
/* do not edit this file - it is machine generated */ #include <jni.h> /* header for class com_tao_test_nativetest */ #ifndef _included_com_tao_test_nativetest #define _included_com_tao_test_nativetest |
然后把上面的第二行的 #include <jni.h>改为#include “jni.h“。让它去调用我们自己的头文件,而不是系统的头文件。
打开jni.h,我们可以找打这么一行
1.#include "jni_md.h"
这个头文件也要我们自己添加,它位于java_home/include/win32目录中,添加方式和前面一致。
④、编写源文件。
新建一个源文件,命名为nativemethod
然后,在里面添加下面代码:
1
2
3
4
5
6
7
8
|
#include "com_tao_test_nativetest.h" //引入头文件 #include <iostream> using namespace std; jniexport void jnicall java_com_tao_test_nativetest_sayhello //本地方法的实现 (jnienv * env, jobject obj) { cout<< "hello world!" <<endl; } |
最后,保存,运行,编译生成dll文件,在工程项目的debug目录中可以找到。
5、将dll文件放入到path环境变量下。
复制dll文件所在路径,加入到path环境变量下。
6、在java中调用我们这个本地方法
1
2
3
4
5
6
7
8
9
|
public class nativetest { static { system.loadlibrary( "nativecode" ); } public native void sayhello(); public static void main(string[] args) { new nativetest().sayhello(); } } |
注意:
1、一般在static代码块中加载动态链接库
2、如果将dll路径加入path环境变量的时候,eclipse是开着的,那么要关闭eclipse再开,让eclipse重新读取环境变量
3、必须在本类中使用native方法
下图表示了我们编写jni的过程
总结
以上所述是小编给大家介绍的较详细的jni简介,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://blog.sina.com.cn/s/blog_9c6852670102wxgw.html