使用本机 JNI 静态方法实现C++ Java 运行时错误

A java runtime error with a native JNI static method for C++ implementation

本文关键字:C++ Java 运行时错误 实现 静态方法 本机 JNI      更新时间:2023-10-16

我有一个存储库,其中包含两个简单的 JNI 和 C/C++ 实现。
我有静态 JNI 方法C++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 本机方法,相同的方法效果很好。 对于没有staticC++工作.

您可以通过以下方式重现相同的行为:
1( 使用静态本机方法取消注释行C++和此方法。并使用 NON 静态本机方法进行注释行,用于C++和这个;
2(只需执行我的 README.md 文件中描述的后续步骤;

有人可以向我解释为什么本机方法静态/非静态适用于 C,而只有本机 NON 静态方法适用于C++?

UPD:我的头文件

/* 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

javah生成的函数的类型根据native方法是否static而有所不同:

JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppstatic
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_MyJNIExample_sayHelloCppnonstatic
(JNIEnv *, jobject);

此外,生成的标头包含一个extern "C"声明,以确保编译器保持名称不变,像__Z29Java_MyJNIExample_sayHelloCppP7JNIEnv_P8_jobject一样。

所以,这里发生的事情是你生成了一个带有static native void sayHelloCpp的头文件,所以有一个带有签名(JNIEnv *, jclass)的函数的extern "C"声明,但你提供了一个(JNIEnv *, jobject)函数。编译器使用其缺省重整方案,因为签名不匹配,并且 Java 运行时无法找到它。

所以,长话短说:如果您更改 Java 类,请始终重新生成头文件并检查C++函数签名。我无法重现您的问题,因为我编写了一个 Makefile,该文件总是在重新编译 Java 文件后重新生成头文件。