Home:ALL Converter>Java calls from different functions in native C using JNI - references lost?

Java calls from different functions in native C using JNI - references lost?

Ask Time:2022-03-24T23:39:11         Author:user2004100

Json Formatter

I am modifying an existing library written in native C to get it to work on Android. To access some hardware elements, I need to use some Java functions. So, I'm using JNI to call Java functions from native C.

My approach is the the following:

  1. Use JNI_OnLoad to get a reference to the Java VM.
  2. Get the JNI environment (JNIEnv)
  3. Find the Java class using FindClass
  4. Create an instance of the Java class using NewObject
  5. Create a reference to the Java method I need to call.

Later on, I call a different function which actually calls the Java method using the previously stored reference. All objects and references are stored in global variables in order to initialize them on JNI_OnLoad and use them at the additional function.

The problem is that when I call the actual Java method I always get 0 (it should return an int). If I check for exceptions, it seems there is one but but I cannot see exactly what is creating the exception.

If I call the method from the JNI_OnLoad function, then it works. This makes me think that some reference is lost when the JNI_OnLoad function exits. I am converting all objects to global references but there must be still something getting lost.

Here is a minimal example of my setup. Any help will be highly appreciated.

Thanks!

JC

Native C:

JNIEnv   *jni_env = NULL;
jclass    jni_cls = NULL;
jobject   jni_obj = NULL;
jmethodID jni_myJavaFunc= NULL;

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    (void)reserved;

    jint ver = JNI_VERSION_1_6;

    if (vm == NULL)
        return JNI_ERR;

    if ((*vm)->GetEnv(vm, (void **)&jni_env, ver) != JNI_OK)
        return JNI_ERR;
        
    jni_cls = (jclass)(*jni_env)->NewGlobalRef(jni_env, (*jni_env)->FindClass(jni_env, "org/java/MyJavaClass"));

    if (jni_cls == NULL)
        return JNI_ERR;

    jmethodID init = (*jni_env)->GetMethodID(jni_env, jni_cls, "<init>", "()V");

    if (init == NULL)
        return JNI_ERR;

    jni_obj = (*jni_env)->NewGlobalRef(jni_env, (*jni_env)->NewObject(jni_env, jni_cls, init));

    if (jni_obj == NULL)
        return JNI_ERR;

    jni_myJavaFunc = (*jni_env)->GetMethodID(jni_env, jni_cls, "myJavaFunc", "()I");

    return ver;
}

int myNativeFunc()
{
    if (jni_myJavaFunc != NULL) {
    
        (*jni_env)->ExceptionClear(jni_env);

        int n = (*jni_env)->CallIntMethod(jni_env, jni_obj, jni_myJavaFunc);
        
        if (!(*jni_env)->ExceptionCheck(jni_env))
            return n;
        else
            return -1;
    }
}

Java class:

public class MyJavaClass extends Activity
{
    public MyJavaClass()
    {

    }
    
    public int myJavaFunc()
    {
        return 1;
    }
}

Author:user2004100,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/71605382/java-calls-from-different-functions-in-native-c-using-jni-references-lost
yy