2

I know there are many questions like this asked before, but I just cannot figure out why my code is not working. So I have a simple class that stores a String:

public class JniString {
    private String mString;

    public JniString() {}

    public String getString() {
        return mString;
    }

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

My JNI code (in C), which is supposed to take JniString object as argument, call setString() function to store some data, and return an integer:

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;
}

And my Java code:

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

But for some reason, this keeps failing with the following error message:

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

I read something about having to call NewGlobalRef() or something since ICS (I'm running my app on KitKat+) over here: http://android-developers.blogspot.ie/2011/11/jni-local-reference-changes-in-ics.html

But I can't understand what the blog post is saying, or where I would put that in the code. Any help would be greatly appreciated. Thanks!

EDIT: I modified the JNI code to be the following:

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;
    }

But now I'm getting a different error:

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
1
  • I'm impressed by how on-point the error message is. Commented Feb 3, 2016 at 20:50

2 Answers 2

2

You're trying to call an instance method via the class instead of via an instance. The second parameter needs to be an object instance of JniString, probably in this case jniString.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer. Im still very new to JNI, can you show me a code that will work?
You can't replace the second parameter of the call with the text I have already given you?
-1

The second parameter of CallVoidMethod() should not be clazz. A nonstatic method needs its this object. Use the jniString parameter instead

There's no warning from the compiler because a jclass is derived from jobject. Typesafe JNI isn't.

1 Comment

There's no warning from the compiler because there is no error, and nothing to warn about, because jclass extends jobject. The call could be correct: for example, you could be calling Class.getName().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.