JNI入门

JNI是Java Native Interface的缩写,Native指C/C++。

JNI内容涉及两个方面:

  • Java调用C,这种情况是最主要的
  • C调用Java,这种情况不常见

第一步:编写Java代码

package haha;
public class Haha {
public native int add(int x, int y);

public native int sub(int x, int y);

public static void main(String[] args) {
   System.loadLibrary("haha");
   Haha haha = new Haha();
   int x = haha.add(3, 6);
   System.out.println(x);
   x = haha.sub(3, 6);
   System.out.println(x);
}
}

定义一个类Haha,它包括两个方法:add和sub,分别是加法和减法。使用Native关键字表明这两个方法是本地方法,无需在Java中给出实现。

注意:加载dll时,不需要带.dll后缀

第二步:javah命令生成头文件

本项目目录结构如下:src/haha/Haha.java,控制台进入到src/目录下,使用javah命令分析haha.Haha.java文件,生成头文件。
javah haha.Haha
注意:

  • javah是jdk安装之后自带的命令,使用之前请确保jdk/bin在环境变量Path中。
  • javah haha.Haha,不需要后缀名.java

第三步:编写C代码

打开VisualStudio,新建win32项目,选择dll作为项目类型。

默认分成头文件、源文件、资源文件三个文件夹,没有必要,把这三个文件夹删掉。

新建haha_Haha.h头文件,把第二步中生成的头文件内容复制进来。
右键项目属性,在VC++/包含目录中,添加JDK/include和JDK/include/win32这两个文件夹(用分号隔开),不要删除原来已经有的目录。

新建“源.cpp”,include 那个头文件,并给出实现:

#include"haha_Haha.h"

JNIEXPORT jint JNICALL Java_haha_Haha_add
(JNIEnv *env, jobject obj, jint x, jint y){
	return x + y;
}

JNIEXPORT jint JNICALL Java_haha_Haha_sub
(JNIEnv *env, jobject obj, jint x, jint y){
	return x - y;
}

最后,点击菜单“生成/生成解决方案(快捷键F7)”或者“生成/重新生成解决方案”,就会在debug目录下找到dll了。

复制上面的dll路径,准备去IntelliJ里面试试能不能加载这个dll

第四步:添加dll运行Java代码

直接运行Java代码会报错:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no haha in java.library.path

看来,必须让java知道dll在哪里,这可以通过java.library.path属性来实现。
点击菜单“Run/Edit Configuration”添加java运行参数

这时运行CTRL+SHIFT+F10运行代码,报错了:
Can't load IA 32-bit .dll on a AMD 64-bit platform
看来,生成的dll是32位的,而我的JDK是64位的(我的系统是64位的)。

切换到VS中,更改项目属性/配置属性,选择64位平台(如果没有x64,点击配置管理器新建平台即可)。之后重新生成dll。

会发现此时dll的目录也发生了改变,所以需要更改java.library.path参数(这个参数跟jar包的classpath是两回事)。

再次运行,终于成功了。

最后

本文只是JNI的入门小例子,更多内容参考《Java核心技术 卷二:高级特性》最后一章。
JNI包括:

  • Java和C中数据类型的对应关系,尤其是String类型,C只支持ASCII码,而Java中的String是Unicode范围。
  • C中代码访问Java静态成员的变量和方法
  • C中代码访问Java对象的成员变量和方法
  • C中变量资源申请和释放
  • C中代码访问Java数组
原文地址:https://www.cnblogs.com/weiyinfu/p/7260906.html