I have my JNI environment and jobject objects saved locally as of now. I found that for my JNI to run of ICS and up devices, I need to fix my JNI code. This is the error I get:
02-20 10:20:59.523: E/dalvikvm(21629): JNI ERROR (app bug): attempt to use stale local reference 0x38100019
02-20 10:20:59.523: E/dalvikvm(21629): VM aborting
02-20 10:20:59.523: A/libc(21629): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 21629
I am confused about how to create/destroy these globals, and if I am even doing it right.
My application currently runs fine on all pre-ICS devices using this code:
BYTE Java_my_eti_commander_RelayAPIModel_00024NativeCalls_InitRelayJava( JNIEnv *env, jobject obj ) {
myEnv = (env);
myObject = obj;
changeID = (*myEnv)->GetStaticMethodID( myEnv, myObject, "changeItJavaWrapper", "(S)V" );
getID = (*myEnv)->GetStaticMethodID( myEnv, myObject, "getItJavaWrapper" , "(S)S" );
putID = (*myEnv)->GetStaticMethodID( myEnv, myObject, "putItJavaWrapper" , "(B)V" );
flushID = (*myEnv)->GetStaticMethodID( myEnv, myObject, "flushItJavaWrapper" , "()V" );
delayID = (*myEnv)->GetStaticMethodID( myEnv, myObject, "delayItJavaWrapper" , "(S)V" );
RelayAPI_SetBaud= WrapSetBaud;
RelayAPI_get = WrapGetIt;
RelayAPI_put = WrapPutIt;
RelayAPI_flush = WrapFlushIt;
RelayAPI_delay = WrapDelayIt;
...
}
Under the GetStaticMethodID
calls, the RelayAPI_ variables are all function pointers that lead here:
void WrapSetBaud( WORD w ) {
return (*myEnv)->CallStaticVoidMethod( myEnv, myObject, changeID, w );
}
short WrapGetIt( WORD time ) {
return (*myEnv)->CallStaticShortMethod( myEnv, myObject, getID, time );
}
void WrapPutIt( BYTE buff ) {
return (*myEnv)->CallStaticVoidMethod( myEnv, myObject, putID, buff );
}
void WrapFlushIt( void ) {
return (*myEnv)->CallStaticVoidMethod( myEnv, myObject, flushID );
}
void WrapDelayIt( WORD wait ) {
return (*myEnv)->CallStaticVoidMethod( myEnv, myObject, delayID, wait );
}
Finally, it returns to my Java code here:
public static void changeItJavaWrapper( short l ) throws IOException {
mModelService.changeitJava( l );
}
public static void flushItJavaWrapper() {
mModelService.flushitJava();
}
public static void putItJavaWrapper( byte p ) {
mModelService.putitJava( p );
}
public static void delayItJavaWrapper( short wait ) {
mModelService.delayitJava( wait );
}
public static short getItJavaWrapper( short s ) throws IOException {
return mModelService.getitJava( s );
}
I have changed my initializations to:
myEnv = (*env)->NewGlobalRef(env,obj);
myObject = (*env)->NewGlobalRef(env,obj);
But i'm extremely confused with this, as they have the same parameters, and it just doesn't make sense. I can't find documentation for this method anywhere as stupid as that sounds, this tutorial
, this page
, and the oracle docs
don't have any information on the NewGlobalRef
method itself.
EDIT
jmethodID changeID;
jmethodID getID;
jmethodID putID;
jmethodID flushID;
jmethodID delayID;
jobject myObject;
jclass bluetoothClass;
JNIEnv *myEnv;