JNI GetLongField失败,"jni对类java.lang.Class的对象无效"

sim*_*mpx 0 java java-native-interface android android-ndk

java代码:

public class Foo {
    private long i = 0;
    void printI() {
        nativePrintI();
    }      
    private native static void nativePrintI();
}
Run Code Online (Sandbox Code Playgroud)

JNI代码:

JNIEXPORT void JNICALL Java_com_aliyun_livestream_Publisher_nativeRelease
    (JNIEnv *env, jobject obj) {
    jclass cls = env->GetObjectClass(obj);;
    jfieldID iField = env->GetFieldID(cls, "i", "J");
    jlong i = env->GetLongField(obj, iField);
    printf("%lld\n", i);
}
Run Code Online (Sandbox Code Playgroud)

我的被​​叫者是这样的:

Foo foo = new Foo();
foo.printI();
Run Code Online (Sandbox Code Playgroud)

有时它工作正常,但有时它失败了消息""jni对类java.lang.Class的对象无效"

Mic*_*ael 5

当您将native方法声明static为时,相应的JNI函数将接收a JNIEnv*和a jclass,以及您指定的任何其他参数(在本例中为none).该jclass参数是对调用该方法的类的引用.
这与您在Java中进行的调用没有什么不同; 当你调用一个static方法时,它将在一个类上调用,而不是从该类实例化的对象.

native另一方面,非静态方法将使用a JNIEnv*和a 调用JNI函数jobject,其中jobject是对调用该方法的对象的引用.

在C/C++中,a jobject和a jclass都是指针,因此你可以将一个指定给另一个,但是当你尝试将它们传递给Java/JNI函数时,那些指针的底层值是什么样的.指向.
GetObjectClassGetLongField期望你传递它们jobject,所以jclass你得到的static情况将无法正常工作.

如果需要jobject,请在Java中将该方法声明为非静态方法.如果需要jclass,请在Java中将该方法声明为static.如果你想要两者,请将它声明为非静态,以便你收到一个jobject你可以调用GetObjectClass的.