利用场景
通过JNI, 实现Java调用C++代码
环境
JDK: jdk-17.0.9
mingw-w64: x86_64-8.1.0-release-win32-seh-rt_v6-rev0
操作系统: windows11
实现步骤
1. 申明native办法
NativeCommand.java
/** * # 生成头文件 * javac -encoding UTF-8 -h . NativeCommand.java * -jni示意生成c++头文件, 从Java 10开始,-jni 选项曾经不再须要了,因为当初 javac -h 默认就会生成C++的头文件。 * */public class NativeCommand { /** * 发送命令给Cpp * @param command 命令 * @param args 参数 * @return 响应 */ public native String send(String command, String... args);}
下面定义了办法public native send(xxx)
2. 生成.h头文件
执行命令即可(如果是JDK8, 须要应用javah命令)javac -encoding UTF-8 -h . NativeCommand.java
jdk17曾经将javah合并到javac中了, 应用javac -h代替javah命令
执行实现后当前目录会生成NativeCommand.h
文件
3. 编写C++代码
NativeCommand.cpp
#include "NativeCommand.h"#include <iostream> JNIEXPORT jstring JNICALL Java_NativeCommand_send (JNIEnv *env, jobject obj, jstring cmd, jobjectArray args) { std::cout<<"Cpp copy, Over"<<std::endl; // std::string hello = "Hello from C++"; return env->NewStringUTF("Over");}
4. 编译dll
g++ -Wall -g -I"boot/include" -I"boot/include/win32" -I"boot/include/win32/bridge" -fPIC NativeCommand.cpp -shared -o nativecmd.dll
将输入nativecmd.dll
其中boot/目录是jdk17的装置目录, 须要改成本人的
5. 加载dll
NativeMain.java
public class NativeMain { static { // 加载dll // 启动参数指定dll目录: -Djava.library.path=D:/WorkspaceVsCode/adswarhead // 打印 java.library.path // String javaLibraryPath = System.getProperty("java.library.path"); // System.out.println(javaLibraryPath); // 这里不要加.dll后缀 System.loadLibrary("nativecmd"); } public static void main(String[] args) { new NativeCommand().send("xxx", args); }}
执行NativeMain, 切记指定java.library.path参数, 指向dll文件所在的目录, 如果在IDEA中执行, 能够参考截图:
输入后果:
谬误状况
1. UnsatisfiedLinkError
异样堆栈:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no nativecmd.dll in java.library.path: D:/WorkspaceVsCode/adswarhead at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2429) at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:818) at java.base/java.lang.System.loadLibrary(System.java:1989) at NativeMain.<clinit>(NativeMain.java:9)
起因: 加载dll失败
解决办法: 查看-Djava.library.path参数, 要设置成dll所在的目录, 示例: -Djava.library.path=D:/WorkspaceVsCode/adswarhead
材料
C++启动JVM并调用Java main办法