0

I'm having a problem with a call to enable the GPS localization from c++. I generated the JNI wrappers with SWIG. The logcat says :

01-02 17:14:03.816: D/dalvikvm(6165): Trying to load lib /data/data/com.example.swig/lib/libcppinterface.so 0x44e7ebf001-02 17:14:03.976: D/dalvikvm(6165): Added shared lib /data/data/com.example.swig/lib/libcppinterface.so 0x44e7ebf001-02 17:14:04.886: W/dalvikvm(6165): JNI WARNING: 0x44e8bb48 is not a valid JNI reference01-02 17:14:04.886: W/dalvikvm(6165):              in Lcom/example/swig/cpplib/cppinterfaceJNI;.LocationSpotter_refresh (JLcom/example/swig/cpplib/LocationSpotter;)V (CallVoidMethodV)01-02 17:14:04.886: I/dalvikvm(6165): "main" prio=5 tid=1 RUNNABLE01-02 17:14:04.886: I/dalvikvm(6165):   | group="main" sCount=0 dsCount=0 s=N obj=0x4001d8e0 self=0xccb001-02 17:14:04.886: I/dalvikvm(6165):   | sysTid=6165 nice=0 sched=0/0 cgrp=default handle=-134502600801-02 17:14:04.886: I/dalvikvm(6165):   | schedstat=( 226108400 549900071 66 )01-02 17:14:04.886: I/dalvikvm(6165):   at com.example.swig.cpplib.cppinterfaceJNI.LocationSpotter_refresh(Native Method)01-02 17:14:04.896: I/dalvikvm(6165):   at com.example.swig.cpplib.LocationSpotter.refresh(LocationSpotter.java:56)01-02 17:14:04.896: I/dalvikvm(6165):   at com.example.swig.MainActivity.onCreate(MainActivity.java:50)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)01-02 17:14:04.896: I/dalvikvm(6165):   at android.os.Handler.dispatchMessage(Handler.java:99)01-02 17:14:04.896: I/dalvikvm(6165):   at android.os.Looper.loop(Looper.java:123)01-02 17:14:04.896: I/dalvikvm(6165):   at android.app.ActivityThread.main(ActivityThread.java:4627)01-02 17:14:04.896: I/dalvikvm(6165):   at java.lang.reflect.Method.invokeNative(Native Method)01-02 17:14:04.896: I/dalvikvm(6165):   at java.lang.reflect.Method.invoke(Method.java:521)01-02 17:14:04.896: I/dalvikvm(6165):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)01-02 17:14:04.896: I/dalvikvm(6165):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)01-02 17:14:04.896: I/dalvikvm(6165):   at dalvik.system.NativeStart.main(Native Method)01-02 17:14:04.906: E/dalvikvm(6165): VM aborting

I trigger the call from Java with this line :

LocationSpotter.getLocationSpotter().refresh();

getLocationSpotter() triggers in c++ this code which creates a jobject (jSpotter) :

// Retrieve the current JNIEnv* with the cached JVMJNIEnv* env;AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");jmethodID construct = env->GetMethodID(clazz, "<init>", "()V");jSpotter = env->NewObject(clazz, construct);

and after the method refresh() triggers this code which makes the application crash :

// Retrieve the current JNIEnv* with the cached JVMJNIEnv* env;AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");jmethodID refresh = env->GetMethodID(clazz, "refresh", "()V");env->CallVoidMethod(jSpotter, refresh); // The line where the crash happens

I also need to mention that I initiate "cachedJVM" in the JNI_OnLoad function. Hope someone could help me on this, thanks

EDIT

Working code :

// Retrieve the current JNIEnv* with the cached JVMJNIEnv* env;AndroidLocationSpotter::cachedJVM->AttachCurrentThread(&env, NULL);jclass clazz = env->FindClass("com/example/swig/AndroidLocationSpotter");jmethodID construct = env->GetMethodID(clazz, "<init>", "()V");jSpotter = env->NewObject(clazz, construct);jSpotter = env->NewGlobalRef(jSpotter);
askedJan 2, 2013 at 18:05
Fr4nz's user avatar

1 Answer1

1

You need to create a new global reference using the returnedjSpotter reference. The reference you are currently using is local to your current frame, and will go out of scope (probably when you DetachCurrentThread()).

You need to callenv->NewGlobalRef(jSpotter) orenv->NewWeakGlobalRef(jSpotter) (both of which have correspondingfree functions) and use the reference returned.

EDIT

Here's an example of proper attach/detach handling (assuming you don't need the thread for further Java operations):

  JNIEnv* env;  JavaVM* jvm = AndroidLocationSpotter::cachedJVM;  int attached = jvm->GetEnv((void *)&env, JNI_VERSION_1_4) == JNI_OK;  if (!attached) {    if (jvm->AttachCurrentThread((void *)&env, NULL) != JNI_OK) {      // Attach failed, handle error condition      return;    }  }  // Pushing a frame ensures proper cleanup of any local references you might generate  // in your JNI code, e.g. with NewLocalRef (optional)                                                                                                                                                                                  if (env->PushLocalFrame(16) < 0) {    // Handle failed frame push error  }  else {    // example local reference generation: ref2 = env->NewLocalRef(ref);    //    // Perform your primary Java operations here    //    env->PopLocalFrame(NULL);  }  if (!attached) {    jvm->DetachCurrentThread();  }
answeredJan 2, 2013 at 21:23
technomage's user avatar
Sign up to request clarification or add additional context in comments.

2 Comments

Hmm ok I'm gonna test that tomorrow. By the way I never call DetachCurrentThread, should I ?
It worked, thanks for your help. For those that are facing the same issue, after puttingenv->NewGlobalRef(jSpotter); in my code, I had another problem when running the app on my device (apparently because of ICS). You should instead writejSpotter = env->NewGlobalRef(jSpotter);. Check the edit to see thoses changes

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.