应用场景
通过JNI, 实现Java调用C++代码
环境
JDK: jdk-17.0.9
mingw-w64: x86_64-13.2.0-release-posix-seh-ucrt-rt_v11-rev1
操作系统: 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。