views:

206

answers:

2

i have an object that is used for calling callback functions ----- static jobject o;

i have assigned the callback function to that object through a pointer, env -----

o=env->NewGlobalRef(callback);

The same pointer, env, points towards the function CallVoidMethod( ) that uses JNI to reach to the java code.

env->CallVoidMethod(o, methodId, pDeviceId, deviceStatus, statusReason, connectionProgressInfo);

However on calling this function, the system is getting crashed, and VM says that it's an invalid reference to static jobject o and then it crashes.

My code is as follows :

static jint android_net_wimax_subscribeDeviceStatusChange(JNIE nv* env, jobject clazz, jobject jdeviceId, jobject callback) {

// LOGD(" android_net_wimax_subscribeDeviceStatusChange() ->D1"); o = env->NewGlobalRef(callback); //o = callback;

// LOGD(" android_net_wimax_subscribeDeviceStatusChange() ->D2");

return (jint)::SubscribeDeviceStatusChange(deviceId, fun_IndDeviceStatusUpdate); }

void fun_IndDeviceStatusUpdate(WIMAX_API_DEVICE_ID_P pDeviceId, WIMAX_API_DEVICE_STATUS deviceStatus, WIMAX_API_STATUS_REASON statusReason, WIMAX_API_CONNECTION_PROGRESS_INFO connectionProgressInfo) {

JNIEnv *env = NULL; int nResult = -1;

// LOGD(" AttachCurrentThread() ->D1");

nResult = g_jVM->AttachCurrentThread(&env, NULL);

// LOGD(" AttachCurrentThread() ->D2-%d",nResult);

if ((nResult != 0) || (env == NULL)) { LOGD(" AttachCurrentThread() failed"); } else { // LOGD(" AttachCurrentThread() ->D3");

if(o == NULL) {

LOGD(" o is NULL ");

} else { LOGD(" o is not NULL ");

}

jclass cls = env->GetObjectClass(o);

// LOGD(" AttachCurrentThread() ->D4"); jmethodID methodId = env->GetMethodID(cls, "callback", "(Landroid/net/wimax/structs/DeviceId;III)V");

// LOGD(" AttachCurrentThread() failed->D5"); if (methodId) { env->CallVoidMethod(o, methodId, pDeviceId, deviceStatus, statusReason, connectionProgressInfo); }

if (g_jVM->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", FUNCTION); } }

// LOGD("JNI->CALLBACK->D3");

}

<<< D/wimax ( 1673): before CallVoidMethod() W/dalvikvm( 1673): JNI WARNING: 0x48e31dec is not a valid JNI reference W/dalvikvm( 1673): in Ldalvik/system/NativeStart;.run ()V (CallVoidMethodV) I/dalvikvm( 1673): "Thread-55" prio=5 tid=45 RUNNABLE I/dalvikvm( 1673): | group="main" sCount=0 dsCount=0 s=N obj=0x43b6c930 self=0x306370 I/dalvikvm( 1673): | sysTid=2000 nice=0 sched=0/0 cgrp=unknown handle=3194272

Kindly help me out

A: 

Without code to look at it's hard to say, but I would guess you're trying to use a local reference after the function it was created in has returned to the VM.

You can get some basic advice from the Android "JNI Tips" document in the Dalvik docs (see "Local vs. Global References"), and more detailed information from the official JNI documentation.

fadden
hey fadden, i have added code as well. kindly have a look at it.
dapper
I'm still not seeing it. You talk about creating a global ref to "callback" called "o", but the CallVoidMethod call that is failing doesn't use either of those. One or more of "pDeviceId", "deviceStatus", "statusReason", or "connectionProgressInfo" is bad. Add a log message that prints all four as hex ("%p") above the CallVoidMethod and see which one matches up with the value shown in the JNI WARNING line.
fadden
hi fadden, i have added the complete source code, maybe you can have a clear understanding now..
dapper
You have "WIMAX_API_DEVICE_ID_P pDeviceId", but you're passing that into the VM as if it were a jobject (first arg to the method is a Landroid/net/wimax/structs/DeviceId;). Make sure that has the correct type, and that it's a global reference if it's being held natively across calls.
fadden
But what I am getting is that the reference to jobject o at " env->callvoidmethod(o,methodId, pDeviceId, deviceStatus, statusReason, connectionProgressInfo); " is invalid. What could be the reason behind this? How can I solve it.
dapper
A: 

Hi,

Try using pastebin or the preformatted tag. In fun_IndDeviceStatusUpdate you reference deviceStatusChangeCB but I do not see where it is declared or assigned. You use o as the static global reference to the callback. Shouldn't o be where you look for the class and not deviceStatusChangeCB?

Fadden is also right that the first argument to the java callback method is an instance of class android/net/wimax/structs/DeviceId. Are you sure that WIMAX_API_DEVICE_ID_P is a jobject instance of that class? Are you sure the error message (can you post that?) is referring to o and not to the argument?

Also, are you sure it is safe to detach the JVM from the thread this method is being invoked from (e.g. is this a Java thread)?

aweisberg
aweisberg, i guess you are right and the error is on the argument only.i have replaced devicestatusChangeCB with o and have added the error log as well.what do u suggest for making WIMAX_API_DEVICE_ID a jobject instance of the class?
dapper
am also getting the following error messages -CALBACK -> ppdeviceId= 0x48e31e38...GetMethodID() ->D5env=0x2C89b0 deviceStatusChangeCB = 0x43b8de08 methodId = 0x412f6620 pdeviceId = 0x48e31e38 DeviceStatus = 5 statusreason=0, connectionprogressinfo=0D/Wimax 1673 before CallVoidMethod()W/dalvikvm JNI warning: 0x48e31dec is not a valid JNI referenceW/dalvikvm is Ldalvik/system/NativeStart, run() V (CallVoidMethod V)I/dalvikvm "Thread-55" prio=5 tid=45 RunnableD/Wimax 1673 before CallVoidMethod()W/dalvikvm JNI warning: 0x48e31dec is not a valid JNI reference
dapper
I don't know what WIMAX_API_DEVICE_ID_P is or where it came from. Assuming there is some logical mapping from a WIMAX_API_DEVICE_ID_P to a android/net/wimax/structs/DeviceId you can instantiate or retrieve an instance of android/net/wimax/structs/DeviceId that corresponds to the instance of WIMAX_API_DEVICE_ID_P that you have.You can use NewObject to instantiate the DeviceId and pick the correct constructor or if it is an enum/singleton type thing you can invoke whatever static methods/getters are available to retrieve the correct one.Also, android/net/wimax/* is not part of the Android API
aweisberg
WIMAX_API_DEVICE_ID_P has been defined as "static WIMAX_API_DEVICE_ID_P pdeviceid ", in some other related file. I used the following code for instantiating WIMAX_API_DEVICE_ID_P --- jobject NewObjectV (JNIEnv *env, jclass cls, jmethodID methodId, WIMAX_API_DEVICE_ID_P pDeviceId); but then i got the following error ---- undefined reference to 'android ::NewObjectV(_JNIEnv *, _jclass *, _jmethod *, _WIMAX_API_DEVICE_ID_P * ).should I use NewGlobalRef to remove this error ? or is there any other way for referencing ?
dapper
Is that a compiler error? I need to see more code to understand what you are doing. "static WIMAX_API_DEVICE_ID_P pdeviceid" is not a definition. It is a declaration of storage for a WIMAX_API_DEVICE_ID_P. Are you sure WIMAX_API_DEVICE_ID_P is a Java object that can be instantiated?"jobject NewObjectV (JNIEnv *env, jclass cls, jmethodID methodId, WIMAX_API_DEVICE_ID_P pDeviceId);", is that a function prototype?
aweisberg
Yeah, its a compiler error. "jobject NewObjectV (JNIEnv *env, jclass cls, jmethodID methodId, WIMAX_API_DEVICE_ID_P pDeviceId);" is not a function prototype. I used this statement to create an object "NewObjectV" and then used it in place of "WIMAX_API_DEVICE_ID_P pdeviceId" in void fun_IndDeviceStatusUpdate(WIMAX_API_DEVICE_ID_P pDeviceId, WIMAX_API_DEVICE_STATUS deviceStatus,WIMAX_API_STATUS_REASON statusReason... )This is when I got the error--undefined reference to 'android ::NewObjectV(_JNIEnv *, _jclass *, _jmethod *, _WIMAX_API_DEVICE_ID_P * )What should be the code to avoid this?
dapper
I need to see the entire code in http://pastebin.com/ to understand what is going on. That doesn't look like a valid method invocation because it specifies a return type as well as the type of all the arguments (which makes it a function prototype). It doesn't look like you can instantiate WIMAX_API_DEVICE_ID_P as a Java object (using env->NewObject) because it is not a jclass reference.
aweisberg