1.native关键词的引入
再完美的编程语言也有自己的不足之处,当然Java也不例外,Java的不足之处除了体现在运行速度(这点往往被一些其他编程语言使用者所诟病)上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native(原生的)关键词来扩展Java程序的功能。native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟环境。简而言之,JNI功能即为:Java和本地代码间的双向交互。JNI允许Java代码使用以其他语言编写的代码和代码库。Invocation API(JNI的一部分)可以用来将Java虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员从本机代码内部调用Java代码。
2.JNI的使用场合
3.JNI的书写步骤
第一步:编写带有native声明的方法的Java类
第二步:使用javac命令编译编写的Java类
第三步:使用java -jni 来生成后缀名为.h的头文件
第四步:使用其他语言(C、C++)实现本地方法
第五步:将本地方法编写的文件生成动态链接库
第六步:运行程序
4.一个JNI的简单应用例子(以HelloJNI为例子)
第一步:编写带有native声明的方法的Java类
public class HelloJNI { public native void displayHelloJNI();//所有native关键词修饰的都是对本地的声明 static { System.loadLibrary("hello");//载入本地库 } public static void main(String[] args) { new JNI().displayHelloJNI(); } }
声明native方法:如果想将一个方法做为一个本地方法的话,那么就必须声明该方法为native,并且不能实现。 Load动态库:System.loadLibrary("hello");加载动态库(可以这样理解:方法 displayHelloJNI()没有实现,但是在后续步骤中就直接使用了,所以必须在使用之前对它进行初始化),这里一般是以static块进行加载的。同时需要注意的是System.loadLibrary()的参数“hello”是动态库的名字。
第二步:使用javac命令编译编写的Java类
javac HelloJNI.java
注意:JDK环境变量的配置
第三步:使用java -jni 来生成后缀名为.h的头文件( 生成扩展名为h的头文件javah HelloJNI)
头文件javah HelloJNI内容如下:
1 /*DO NOT EDI TTHIS FILE - it is mach inegenerated*/ 2 #include3 /*Header for class HelloJNI*/ 4 5 #ifndef_Included_HelloJNI 6 #define_Included_HelloJNI 7 #ifdef__cplusplus 8 extern"C"{ 9 #endif 10 /* 11 *Class:HelloJNI 12 *Method:displayHelloJNI 13 *Signature:()V 14 */ 15 JNIEXPORTvoidJNICALL 16 Java_HelloJNI_displayHelloJNI(JNIEnv*,jobject); 17 18 #ifdef__cplusplus 19 } 20 #endif 21 #endif
注意:这个h文件相当于在java里面的接口,这里声明了一个Java_HelloJNI_displayHelloJNI (JNIEnv *, jobject)方法,然后在本地方法里面实现这个方法,也就是说在编写C/C++程序的时候所使用的方法名必须和这里的一致
第四步:使用其他语言(C、C++)实现本地方法(编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法)
1 #include"jni.h" 2 #include"HelloJNI.h" 3 4 //#includeotherheaders 5 6 JNIEXPORT void JNICALL 7 Java_HelloJNI_displayHelloJNI(JNIEnv*env,jobject obj) 8 { 9 printf("HelloJNI!\n"); 10 return; 11 }
注意:代码第一行需要将jni.h(该文件可以在%JAVA_HOME%/include文件夹下面找到)文件引入,因为在程序中的JNIEnv、 jobject等类型都是在该头文件中定义的;另外在第2行需要将HelloJNI.h头文件引入,然后保存为 HelloJNIImpl.c。
第五步:将本地方法编写的文件生成动态链接库