I'm working in the JNI Invocation API, calling into Java from C. I have some upfront initialization to cache 30+ Java classes into global references. The results of FindClass are passed into NewGlobalRef to acquire a global reference to the class. I'm caching these class variables to reuse them later. I have 30+ global references to classes (and 30+ global methodIDs for the class constructors).
In the following sample, I've removed exception handling as well as JNI invocation for the purpose of shortening the code snippet. My working code has exception checks after every JNI call and I'm running with -Xcheck:jni. Here's the snippet:
jclass aClass;
jclass bClass;
jmethodID aCtor;
jmethodID bCtor;
void getGlobalRef(const char* clazz, jclass* globalClass)
{
jclass local = (*jenv)->FindClass(jenv,clazz);
if (local)
{
*globalClass = (jclass) (*jenv)->NewGlobalRef(jenv,local);
(*jenv)->DeleteLocalRef(jenv,local);
}
}
methodID getMethodID(jclass clazz, const char* method, const char* sig)
{
return (*jenv)->GetMethodID(jenv,clazz,method,sig);
}
void initializeJNI()
{
getGlobalRef("MyProj/Testclass1", &aclass);
getGlobalRef("MyProj/Testclass2", &bclass);
.
.
aCtor = getMethodID(aclass,"<init>","()V");
bCtor = getMethodID(bclass,"<init>","(I)V");
}
The initializeJNI() function sets the global references for jclasses and method IDs for constructors as well as some jfieldID's and some initialization of C data structures.
After initialization, when I call into a JNI function using some of the cached jclasses and ctor jmethodIDs, I get a bad global or local reference calling reported from the -Xcheck:jni.
In gdb, I break at the last line of initializeJNI(), and print all jclasses and jmethodIDs and the ones causing problems look to have been turned into garbage or garbage-collected (i.e. 0x00 or 0x06). Is it possible for global references to be gc'ed?
Any suggestions?