First time I used JNI to access a c library and I thought of using valgrind to check for any memory leaks. Valgrind reported so many leaks in jvm.:(
Used Push/Poplocal frame for managing local references and of course releasing references from Get(UTFChars/Arrays) which needs be. Aside from that it also reports a possible lost in AttachCurrentThread method when in fact I detached it successfully through DetachCurrentThread in my call back function.
And now I just need advise/explanation that the reported leaks were not true at all and will not affect my application especially its on the server side. Well for me I suspect that the unloading of the library and destroying had not yet been done after my app exits and valgrind already did its checking part. Hope to hear from anyone who had experience this kind of case as well.
//sample code
void event_callback(void .., int ..)
{
printf("--Enter event_callback Function--\n");
int detach = 0;
//store our jnienv for this thread
JNIEnv *g_env = NULL;
// if our jni env is not attached for this thread, then we will attach it
int getEnvStat = (*g_jvm)->GetEnv(g_jvm, (void **)&g_env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED)
{
//if not attached, then lets attached g_env
printf("JNIEnv not attached. Attaching..\n");
if ((*g_jvm)->AttachCurrentThread(g_jvm, (void **) &g_env, NULL) != 0)
{
printf("Failed to attach\n");
return;
}
else
{
detach = 1;
}
}
else if (getEnvStat == JNI_OK)
{
printf("GetEnv: jenv is just OK, already attached.\n");
}
else if (getEnvStat == JNI_EVERSION)
{
printf("GetEnv: version not supported\n");
return;
}
if((*g_env)->PushLocalFrame(g_env, 10)<0)
{
printf("Out of memory\n");
}
//...some useful code here
(*g_env)->PopLocalFrame(g_env, NULL);
if(detach == 1)
{
int result = (*g_jvm)->DetachCurrentThread(g_jvm);
printf("DetachCurrentThread result: %d\n", result);
}
printf("--Exit event_callback Function--\n");
}
Report:
==20914== 432 bytes in 1 blocks are possibly lost in loss record 903 of 1,035
==20914== at 0x4028876: malloc (vg_replace_malloc.c:236)
==20914== by 0x4950461: os::malloc(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x464470C: CHeapObj::operator new(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x496BB13: ParkEvent::Allocate(Thread*) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4A13CCD: Thread::Thread() (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4A15091: JavaThread::JavaThread(bool) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4853723: attach_current_thread.isra.103.part.104 (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x7B17791: event_callback (in /home/Wrapper/TJNIBridge/libJNIBridge.so)
==20914== by 0x7B44431: xmpp_event_main (my_xmpp.c:562)
==20914== by 0x412146D: clone (clone.S:130)
I also pasted some of the reported leaks below all from jvm lib.
==20914== 4,612 (1,284 direct, 3,328 indirect) bytes in 1 blocks are definitely lost in loss record 1,009 of 1,035
==20914== at 0x4028876: malloc (vg_replace_malloc.c:236)
==20914== by 0x4950461: os::malloc(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x464470C: CHeapObj::operator new(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4A14BE9: WatcherThread::start() (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4A192DF: Threads::create_vm(JavaVMInitArgs*, bool*) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4865BD8: JNI_CreateJavaVM (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x41ECD30: start_thread (pthread_create.c:304)
==20914== by 0x412146D: clone (clone.S:130)
==20914== 8 bytes in 1 blocks are definitely lost in loss record 41 of 1,035
==20914== at 0x4028876: malloc (vg_replace_malloc.c:236)
==20914== by 0x4950461: os::malloc(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x464470C: CHeapObj::operator new(unsigned int) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x470E29D: CSpaceCounters::CSpaceCounters(char const*, int, unsigned int, ContiguousSpace*, GenerationCounters*) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x47A3BF9: DefNewGeneration::DefNewGeneration(ReservedSpace, unsigned int, int, char const*) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x47FC623: GenerationSpec::init(ReservedSpace, int, GenRemSet*) (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x47EF9D4: GenCollectedHeap::initialize() (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
==20914== by 0x4B95FF3: ??? (in /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/client/libjvm.so)
Ubuntu 11.10 OpenJDK 7