JNI技术学习(一):在JAVA中调用C++/C代码 JNI

博主近期在实习,遇到一个需要,就是如何在JAVA代码中调用C++的算法。背景:已经有封装好的C++算法,然后现在要用JAVA语言编写一个平台,要在平台中调用已经写好的C++代码。这里我们就要借助:JNI。
JNI是Java Native Interface的缩写,它是JDK的一部分,提供了若干的API实现Java和其他语言的通信(主要是C或C++)。但这种有一个缺点就是使用Java与本地已编译的代码交互,通常会丧失平台可移植性。但有一些情况下,是可以接受的,甚至是必须的。例如使用一些旧的库,或者与硬件、操作系统进行交互等。(这里要注意,JNI也可以让C++代码调用JAVA代码)
接下来我们就借助JNI实现一个简单从JAVA中调用C++代码的HelloWorld。

1. 编写JAVA代码

JNI技术学习(一):在JAVA中调用C++/C代码 JNI
我们注意到,上图的代码中,出现了 native 关键字,这里,我们先介绍一下 native 关键字:

  • native关键词修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在其他语言中实现的。
  • 这里编写带有native声明的方法的java文件,就是表明了有对应其他语言实现了这些方法。

2. 生成头文件

先执行 javac 指令,生成对应的 .class 文件
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
再执行 javah 指令,生成对应的头文件
javah -classpath xx -jni yy
其中 xx 为 src 文件夹的目录
yy 为包名 + class文件名
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
生成头文件:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI

3. 创建其他语言的工程

我们这里选择实现C++语言的例子,工程搭建过程如下:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
JNI技术学习(一):在JAVA中调用C++/C代码 JNI

JNI技术学习(一):在JAVA中调用C++/C代码 JNI
生成项目文件后,我们要导入以下的三个头文件
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
其中,

  • aa_bb_cc_Hello.h:为之前 JAVA 代码生成的头文件
  • jni_md.h:在jdk包内,路径:\Java\jdk1.8.0_152\include\win32
  • jni.h:在 jdk包内,路径:\Java\jdk1.8.0_152\include

这里要注意:要修改导入 JAVA 代码生成的头文件:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
修改为:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI

4. 编写C++代码

JNI技术学习(一):在JAVA中调用C++/C代码 JNI

5. 生成dll文件

JNI技术学习(一):在JAVA中调用C++/C代码 JNI
JNI技术学习(一):在JAVA中调用C++/C代码 JNI

6. 编写 JAVA 代码,实现调用 C++ 函数

JNI技术学习(一):在JAVA中调用C++/C代码 JNI
这里 System.loadLibrary("") 导入 dll 或 so 文件
但我们尝试执行,发现报错:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
这里没有 java.library.path ,我们进行配置:
在项目处右键:Properties -》Java Build Path -》Source -》Native library location
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
在这里配置存放 dll 或 so 的文件目录
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
切到 Libraries -》 Native library location
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
在这里配置存放 dll 或 so 的文件目录
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
再次尝试运行,但是发现还是报错,为什么呢?
JNI技术学习(一):在JAVA中调用C++/C代码 JNI
这里是因为,生成的dll,是在 win32 的环境下生成的,32位的dll,但是 JDK 是64位的,这里处理的方式有两种,一个是通过 VS 环境下生成 win64 的dll,另外一种方式就是使用32位的 JDK,我这里使用32位的 JDK 重新创建 JAVA 项目,成功运行:
JNI技术学习(一):在JAVA中调用C++/C代码 JNI