【问题标题】:Calling a method in a Java object from JNI returns error从 JNI 调用 Java 对象中的方法返回错误
【发布时间】:2016-02-03 01:31:28
【问题描述】:

我知道以前有人问过很多这样的问题,但我就是不知道为什么我的代码不起作用。所以我有一个简单的类来存储一个字符串:

public class JniString {
    private String mString;

    public JniString() {}

    public String getString() {
        return mString;
    }

    public void setString(String s) {
        mString = s;
    }
}

我的JNI代码(C语言),它应该以JniString对象作为参数,调用setString()函数来存储一些数据,并返回一个整数:

JNIEXPORT jint
        JNICALL Java_com_sample_MyClass_test(JNIEnv *env, jobject thiz, jobject jniString) {
    jclass clazz = (*env)->FindClass(env, "com/sample/JniString");
    jmethodID methodId = (*env)->GetMethodID(env, clazz, "setString", "(Ljava/lang/String;)V");

    jstring placeholder = (*env)->NewStringUTF(env, "placeholder");
    (*env)->CallVoidMethod(env, clazz, methodId, placeholder);

    return 1;
}

还有我的 Java 代码:

JniString jniString = new JniString();
// Call test() JNI function with jniString as argument

但由于某种原因,这一直失败并显示以下错误消息:

05-24 23:27:23.099    7575-7575/? A/art﹕ art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: can't call void com.sample.JniString.setString(java.lang.String) on instance of java.lang.Class<com.sample.JniString>
05-24 23:27:23.099    7575-7575/? A/art﹕ art/runtime/java_vm_ext.cc:410]     in call to CallVoidMethod

我在这里读到了一些关于必须调用 NewGlobalRef() 或自 ICS(我在 KitKat+ 上运行我的应用程序)以来的内容:http://android-developers.blogspot.ie/2011/11/jni-local-reference-changes-in-ics.html

但我不明白博文在说什么,也不明白我会把它放在代码中的什么地方。任何帮助将不胜感激。谢谢!

编辑: 我修改了JNI代码如下:

JNIEXPORT jint
            JNICALL Java_com_sample_MyClass_test(JNIEnv *env, jobject thiz, jobject jniString) {
        jclass clazz = (*env)->GetObjectClass(env, jniString);
        jmethodID methodId = (*env)->GetMethodID(env, clazz, "setString", "(Ljava/lang/String;)V");

        jstring placeholder = (*env)->NewStringUTF(env, "placeholder");
        (*env)->CallVoidMethod(env, jniString, methodId, placeholder);

        return 1;
    }

但现在我得到了一个不同的错误:

05-25 19:11:02.832    8802-8802/com.sample E/art﹕ JNI ERROR (app bug): attempt to use stale local reference 0x1 (should be 0x100001)
05-25 19:11:02.850    8802-8802/com.sample A/art﹕ art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x1

【问题讨论】:

  • 错误消息的准确程度给我留下了深刻的印象。

标签: java android android-ndk java-native-interface


【解决方案1】:

您试图通过类而不是通过实例调用实例方法。第二个参数需要是JniString的对象实例,本例中可能是jniString

【讨论】:

  • 感谢您的回答。我对 JNI 还是很陌生,你能告诉我一个可行的代码吗?
  • 你不能用我已经给你的文字替换调用的第二个参数吗?
【解决方案2】:

CallVoidMethod()的第二个参数不应该是clazz。非静态方法需要其this 对象。请改用jniString 参数

编译器没有警告,因为jclass 派生自jobject。类型安全的 JNI 不是。

【讨论】:

  • 编译器没有警告,因为没有错误,也没有什么可警告的,因为 jclass 扩展了jobject。调用可能是正确的:例如,您可以调用 Class.getName().
猜你喜欢
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
相关资源
最近更新 更多