1、关于原生关键字
想必读者已经知道 native 关键字了。在这里,作者将大致介绍一下。被 native 关键字修饰的方法称为本地方法。本机方法不同于其他方法。 native方式意味着它与平台有关,所以使用native的程序的可移植性不是很高。另外,native方法的数据区在JVM中运行时与其他方法不同。它有一个专用的本机方法堆栈。 native 方法主要用于加载文件和动态链接库。由于Java语言无法访问操作系统的底层信息(如:底层硬件设备等),所以需要使用C语言来完成。 native修改的方法可以被C语言覆盖。
2、使用原生关键字
2.1、使用步骤
2.2、案例
为了更好理解,本例中的所有文件都在 D:\JNI\ 目录下。
2.2.1 写一个.java文件
public class HelloWorld{ public native void h();//该方法和abstract修饰的方法一样,只有签名。 static{ System.loadLibrary("hello");//不写文件的后缀,程序会自动加上.dll的。 } public static void main(String[] args){ new HelloWorld().h();//调用 } }
2.2.2 编译.java文件
在AMD编译程序javac HelloWorld.java,会生成一个HelloWorld.class文件。
2.2.3 获取.h文件
将第二步生成的字节码文件通过javah -jni HelloWorld传递,生成HelloWorld.h文件。
我们用记事本打开HelloWorld.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: h * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_h (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
可以看到HelloWorld.java文件中的h()方法变成了JNIEXPORT void JNICALL Java_HelloWorld_h (JNIEnv *, jobject); ,方法名就是原来的包名_类名_方法名。该文件中还引用了jni.h文件。
2.2.4 写hello.cpp文件
hello.cpp文件的写法有很多种,可以使用Visual Studio软件,因为最后需要生成dll文件,所以在下载Visual Studio之前要检查版本是否可以生成dll您的计算机所需的版本(32 位 dll 版本)或 64 位 dll)。读者这里下载vs2013,可以生成32位dll和64位dll。 vs2013生成dll请参考Visual Studio 2013生成64位dll
因为我们第一步调用的文件名是hello,所以这里的.cpp文件一定是hello.cpp文件。这里作者的文件如下:
可以看出引入了HelloWorld.h文件,所以hello.cpp文件应该和HelloWorld.h文件在同一目录下。如果读者现在编译hello.cpp文件,会报错“jni.h”: No such file or directory 。在HelloWorld.h文件中,我们引入了jni.h文件,所以jni.h文件也应该放在同级目录下。关于这个文件及相关文件的读者可以到JDK安装目录下的include中查找,更多信息可以查看JDK、JRE、JVM之间的关系。您还应该将 HelloWorld.h 文件中的 #include 更改为 #include “jni.h” 。最后就可以生成hello.dll文件了。
2.2.5 部署hello.dll文件
我们使用 System.loadLibary(“hello”);加载动态链接库,这个加载路径是根据 java.libary.path 查询的,读者可以根据 System.getProperty(“java.libary.path”) 来验证,path就是环境变量中的path路径。网上很多说法都是hello.dll还在C:\Windows\System32路径下。不过作者建议还是先检查一下自己的环境变量path的值,然后把hello.dll放到path中配置的第一个路径中。
2.2.6 运行 HelloWorld.class 文件
我们回到D:/JNI路径,使用java HelloWorld成功调用动态链接库。
我成功打印了hello!在我的控制台上。笔者这里对加载的理解是利用反射机制在运行时找到hello.dll文件并解析64位系统不能调32位dll64位系统不能调32位dll,根据动态链接库中的文件名创建对象和方法,然后我们就可以使用对象调用方法了在上面的HelloWorld.java文件中,创建动态链接库和调用方法都在同一个类中,所以只需要使用这个类的对象调用方法就可以编译运行了。如果我们引入人的.cpp文件,那么根据.cpp文件中的方法名,在需要的地方进行适当的调整即可调用。
写在最后:本人是跨行java初学者,希望大家一起交流学习。文章如有问题,请指正。
请登录后发表评论
注册
社交帐号登录