关于jni:C实现Java-native方法

41次阅读

共计 1944 个字符,预计需要花费 5 分钟才能阅读完成。

利用场景

通过 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 办法

正文完
 0