C++ 实现的本机 JNI 静态方法出现 java 运行时错误
A java runtime error with a native JNI static method for C++ implementation
我有一个 two simple implementations 的回购协议,用于 JNI C/C++。
我有 C++ 静态 JNI 方法的 java.lang.UnsatisfiedLinkError
错误。
(base) GlushenkovYuri:java y.glushenkov$ /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/bin/java -Djava.library.path=. MyJNIExample
Hello World from C!
Exception in thread "main" java.lang.UnsatisfiedLinkError: MyJNIExample.sayHelloCpp()V
at MyJNIExample.sayHelloCpp(Native Method)
at MyJNIExample.main(MyJNIExample.java:51)
但对于 C 本机方法,同样的方法效果很好。
对于没有 static
.
的 C++ 作品
您可以通过以下方式重现相同的行为:
1) 取消注释行 the static native method for C++ and this one. And comment lines with the NON static native method for C++ and this one;
2) 然后执行我的 README.md 文件中描述的后续步骤;
有人可以向我解释为什么本机方法 static/non static 适用于 C,但只有本机 NON static 方法适用于 C++ 吗?
更新:我的 header 文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyJNIExample */
#ifndef _Included_MyJNIExample
#define _Included_MyJNIExample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MyJNIExample
* Method: sayHelloC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloC
(JNIEnv *, jclass);
/*
* Class: MyJNIExample
* Method: sayHelloCpp
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCpp
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
根据native
方法是否为static
,javah
生成的函数类型不同:
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppstatic
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppnonstatic
(JNIEnv *, jobject);
此外,生成的 header 包含一个 extern "C"
声明,以确保编译器保持名称完好无损,就像 __Z29Java_MyJNIExample_sayHelloCppP7JNIEnv_P8_jobject
.
所以,这里发生的事情是你生成了一个 header 文件,带有 static native void sayHelloCpp
,所以有一个带有签名 (JNIEnv *, jclass)
的函数的 extern "C"
声明,但是你 提供 一个 (JNIEnv *, jobject)
函数。编译器使用其默认的修改方案,因为签名不匹配,Java 运行时无法找到它。
所以,长话短说:始终 重新生成您的 header 文件,并在您更改 Java class 时检查 C++ 函数签名。我无法重现您的问题,因为我编写了一个 Makefile,它总是在重新编译 Java 文件后重新生成 header 文件。
我有一个 two simple implementations 的回购协议,用于 JNI C/C++。
我有 C++ 静态 JNI 方法的 java.lang.UnsatisfiedLinkError
错误。
(base) GlushenkovYuri:java y.glushenkov$ /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/bin/java -Djava.library.path=. MyJNIExample
Hello World from C!
Exception in thread "main" java.lang.UnsatisfiedLinkError: MyJNIExample.sayHelloCpp()V
at MyJNIExample.sayHelloCpp(Native Method)
at MyJNIExample.main(MyJNIExample.java:51)
但对于 C 本机方法,同样的方法效果很好。
对于没有 static
.
您可以通过以下方式重现相同的行为:
1) 取消注释行 the static native method for C++ and this one. And comment lines with the NON static native method for C++ and this one;
2) 然后执行我的 README.md 文件中描述的后续步骤;
有人可以向我解释为什么本机方法 static/non static 适用于 C,但只有本机 NON static 方法适用于 C++ 吗?
更新:我的 header 文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MyJNIExample */
#ifndef _Included_MyJNIExample
#define _Included_MyJNIExample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MyJNIExample
* Method: sayHelloC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloC
(JNIEnv *, jclass);
/*
* Class: MyJNIExample
* Method: sayHelloCpp
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCpp
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
根据native
方法是否为static
,javah
生成的函数类型不同:
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppstatic
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppnonstatic
(JNIEnv *, jobject);
此外,生成的 header 包含一个 extern "C"
声明,以确保编译器保持名称完好无损,就像 __Z29Java_MyJNIExample_sayHelloCppP7JNIEnv_P8_jobject
.
所以,这里发生的事情是你生成了一个 header 文件,带有 static native void sayHelloCpp
,所以有一个带有签名 (JNIEnv *, jclass)
的函数的 extern "C"
声明,但是你 提供 一个 (JNIEnv *, jobject)
函数。编译器使用其默认的修改方案,因为签名不匹配,Java 运行时无法找到它。
所以,长话短说:始终 重新生成您的 header 文件,并在您更改 Java class 时检查 C++ 函数签名。我无法重现您的问题,因为我编写了一个 Makefile,它总是在重新编译 Java 文件后重新生成 header 文件。