2010-07-29 2 views
0

у меня есть объект, который используется для вызова функции обратного вызова:Недопустимая ссылки во время обратного вызова

static jobject o; 

я назначенный функцию обратного вызова для этого объекта через указатель:

o=env->NewGlobalRef(callback); 

Тот же указатель, env, указывает на функцию CallVoidMethod, которая использует JNI для доступа к Java-коду.

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

Однако при вызове этой функции, система становится разбилась, и VM говорит, что это недопустимая ссылка на статический jobject о и затем он выходит из строя.

Мой код выглядит следующим образом:

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): перед тем CallVoidMethod() W/dalvikvm (1673): JNI ВНИМАНИЕ: 0x48e31dec не является допустимым ссылка JNI

Вт/dalvikvm (1673): в Ldalvik/системы/NativeStart; .run() V (CallVoidMethodV)

I/dalvikvm (1673): "резьба-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 приятно = 0 Плановое = 0/0 КГП = неизвестная ручка = 3194272

Пожалуйста, помогите мне

ответ

0

без кода, чтобы посмотреть на это трудно сказать, но я предполагаю, что вы пытаетесь используйте локальную ссылку после того, как функция, которую она создала, вернулась в виртуальную машину.

Вы можете получить базовые рекомендации от документа «Советы JNI» Android в Dalvik docs (см. «Местные и глобальные ссылки») и более подробную информацию из официальной документации JNI.

+0

эй фадден, я добавил код. любезно взгляните на него. – dapper

+0

Я все еще не вижу этого. Вы говорите о создании глобального ref для «callback», называемого «o», но вызов CallVoidMethod, который терпит неудачу, не использует ни один из них. Один или несколько из «pDeviceId», «deviceStatus», «statusReason» или «connectionProgressInfo» являются плохими.Добавьте сообщение журнала, которое выводит все четыре в виде шестнадцатеричного («% p») над CallVoidMethod и показывает, какой из них соответствует значению, указанному в строке JNI WARNING. – fadden

+0

hi fadden, я добавил полный исходный код, может быть, теперь у вас может быть четкое понимание. – dapper

0

Попробуйте использовать пастабин или предварительно отформатированный тег. В fun_IndDeviceStatusUpdate вы ссылаетесь на deviceStatusChangeCB, но я не вижу, где он объявлен или назначен. Вы используете o как статическую глобальную ссылку на обратный вызов. Не должно быть где искать класс, а не deviceStatusChangeCB?

Fadden также прав, что первый аргумент метода java callback является экземпляром класса android/net/wimax/structs/DeviceId. Вы уверены, что WIMAX_API_DEVICE_ID_P является экземпляром задания для этого класса? Вы уверены, что сообщение об ошибке (можете ли вы опубликовать это?) Ссылается на o, а не на аргумент?

Кроме того, вы уверены, что безопасно отсоединить JVM от потока, с которым этот метод вызывается (например, является ли это потоком Java)?

+0

aweisberg, я думаю, вы правы, и ошибка только в аргументе. Я заменил devicestatusChangeCB на o и добавил журнал ошибок. Что вы предлагаете для создания WIMAX_API_DEVICE_ID экземпляра задания для класса? – dapper

+0

am также получают следующие сообщения об ошибках - CALBACK -> ppdeviceId = 0x48e31e38 . . . GetMethodID() -> Д5 ENV = 0x2C89b0 deviceStatusChangeCB = 0x43b8de08 methodId = 0x412f6620 pdeviceId = 0x48e31e38 DeviceStatus = 5 statusreason = 0, connectionprogressinfo = 0 Д/Wimax 1673 перед тем CallVoidMethod() Вт/dalvikvm предупреждение JNI : 0x48e31dec не является допустимым JNI ссылка Вт/dalvikvm является Ldalvik/система/NativeStart, запустить() V (CallVoidMethod V) I/dalvikvm "резьба-55" PRIO = 5 TID = 45 Runnable Д/Wimax тысячу шестьсот семьдесят-три до CallVoidMethod() W/dalvikvm Предупреждение JNI: 0x48e31dec не является действительным ссылкой JNI – dapper

+1

Я не знаю, что такое WIMAX_API_DEVICE_ID_P или откуда оно взялось. Предполагая, что существует некоторое логическое отображение из WIMAX_API_DEVICE_ID_P в android/net/wimax/structs/DeviceId, вы можете создать экземпляр или получить экземпляр android/net/wimax/structs/DeviceId, который соответствует экземпляру WIMAX_API_DEVICE_ID_P, который у вас есть. Вы можете использовать NewObject для создания экземпляра DeviceId и выбора правильного конструктора, или если это элемент типа enum/singleton, который вы можете вызвать, какие бы статические методы/геттеры не были доступны для получения правильного. Кроме того, android/net/wimax/* не является частью API Android – aweisberg

Смежные вопросы