venky
venky

Reputation: 2381

"this" is not a valid JNI reference in Android JNI

I am passing the current activity to the native method using Java Native Interface on android. But I am not doing it using JNI like function names. I am registering native functions manually.

This works (JNI naming).

com_venkatesh_home.c

JNIEXPORT void JNICALL Java_com_venkatesh_Home_doStuff(JNIEnv *env, jobject activity) {
    jclass Activity = (*env)->GetObjectClass (env, activity);

com.venkatesh.Home.java

private native void doStuff();
static {
    System.loadLibrary("venkatesh");
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    doStuff();
 }


But this does not work. (Manual registration and passing activity as an object)

me.c

static JavaVM *java_vm;

void do_stuff (jobject activity)
{
    JNIEnv *env;
    if ((*java_vm)->GetEnv(java_vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        LOG_D("GetEnv failed");
        return -1;
    }

    jclass Activity = (*env)->GetObjectClass (env, activity);
}

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

    JNIEnv* env;
    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        LOG_D ("GetEnv failed.");
        return -1;
    }

    // Find the class calling native function
    jclass Home = (*env)->FindClass(env, "com/venkatesh/Home");
    if (Home == NULL) {
        LOG_D ("FindClass failed : No class found.");
        return -1;
    }

    // Register native method for getUsbPermission
    JNINativeMethod nm[1] = {
        { "doStuff", "(Landroid/app/Activity;)V", do_stuff}
    };

    if ((*env)->RegisterNatives(env, NativeUsb, nm , 1)) {
         LOG_D ("RegisterNatives Failed.");
         return -1;
    }

    return JNI_VERSION_1_6;
}

com.venkatesh.Home.java

private native void doStuff(Activity activity);
static {
    System.loadLibrary("venkatesh");
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    doStuff(this);
 }

The error is

JNI WARNING: 0xb89a7788 is not a valid JNI reference (GetObjectClass)

where 0xb89a7788 is the "this" received on jni side as activity.

Now, as I understand this represents the present object. Equivalent to self in python. But then I am passing an object to the native side and hence it should be a valid reference. Why the invalid reference error? It this not an object? What is wrong?

Upvotes: 0

Views: 541

Answers (1)

David M. Lloyd
David M. Lloyd

Reputation: 2825

This is happening not because of how the method is being registered, but because of the signature of your native method. I would rewrite that method like this:

void do_stuff (JNIEnv *env, jobject this, jobject activity)
{
    jclass Activity = (*env)->GetObjectClass (env, activity);
    // ...and whatever else you want...
}

Every JNI method must take a JNIEnv * as its first parameter. (Note also the lack of the static env variable - it isn't needed). Also, since it is not a static method, the first parameter passed in to the method will be this and not activity.

Upvotes: 3

Related Questions