Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jni table overflow even after deleteLocalRef

When I run the code, I get an error "failed adding to JNI local ref table has 512 entries"

This is my code:

jstring pJNIData = pJNIEnv->NewStringUTF ( variables[0].GetStringValue() );

pJNIEnv->CallStaticVoidMethod ( pJNIActivityClass, pJNIMethodIDStartTime, pJNIData ) ;

pJNIEnv->DeleteLocalRef(pJNIData);

I have read several suggestions, but none of them work! In spite of the DeleteLocalRef, it fails to works. The function is used in a profiler that literally calls all the functions...

like image 697
shehzad_ucdavis Avatar asked Aug 23 '12 09:08

shehzad_ucdavis


1 Answers

I have seen this when a JNI method called Java code (in my case, the method was not static). As I understand, unused local references are not automatically deleted when a Java method is called from JNI (I mean, until the top-level JNI function returns).

IIRC either there already was information about memory objects in the log, or I could add some logging; from that information I identified garbage items that I did not mention before. They were two arrays and a class, created in subsequent calls but not garbage-collected.

// in a function that calls a Java method from JNI
jbyteArray srcArray = env->NewByteArray(len);
jclass cls = env->FindClass("com/something/MyClass");
jmethodID mid = env->GetMethodID(cls, "mymethod", "([BI)[B");
jbyteArray resArray = (jbyteArray)env->CallObjectMethod(obj, mid, srcArray, XXXX);

...
env->DeleteLocalRef(cls);
env->DeleteLocalRef(resArray);
env->DeleteLocalRef(srcArray);
// no need to do anything with mid

Note that although these three local references were obtained differently, all of them were hanging around.

Useful link: http://www.netmite.com/android/mydroid/dalvik/docs/jni-tips.html#local_vs_global_references (or find the Dalvik VM docs dalvik/docs/jni-tips.html and locate the section "Local vs. Global References")

Every object that JNI returns is a "local reference". This means that it's valid for the duration of the current native method in the current thread. Even if the object itself continues to live on after the native method returns, the reference is not valid. This applies to all sub-classes of jobject, including jclass and jarray. [...] Note: method and field IDs are just 32-bit identifiers, not object references, and should not be passed to NewGlobalRef. The raw data pointers returned by functions like GetStringUTFChars and GetByteArrayElements are also not objects.

like image 184
18446744073709551615 Avatar answered Oct 10 '22 04:10

18446744073709551615