VisualStudio中的native关键字修饰方法

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初学者,希望大家一起交流学习。文章如有问题,请指正。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论