Saturday, June 21, 2008

JNI's NewStringUTF and Memory Use

After a few crashes and debugging returning the error location being a malloc call, I did some research on NewStringUTF usage.

It was difficult to find, but it appears that a returned jstring (made by NewStringUTF) is copied by Java into its own heap space. This contradicts my previous assumption that it just kept the memory pointer. In my previous code I had similar to:



JNIEXPORT jstring JNICALL Java_myClass_myMethod(JNIEnv *env, jobject obj){
...
LPTSTR buffer = (LPTSTR)malloc(200*sizeof(TCHAR));
...
return env->NewStringUTF(buffer);
}


Obviously this doesn't free the memory allocated and pointed to by "buffer" - which I'd previously thought was correct, assuming the Java garbage collector would clean it up. It appears that was incorrect, though - so (in my situation) the best solution was to make a global buffer and use it over and over.


LPTSTR buffer = (LPTSTR)malloc(200*sizeof(TCHAR));
JNIEXPORT jstring JNICALL Java_nimbus_getForegroundWindow(JNIEnv *env, jobject obj){
...
return env->NewStringUTF(buffer);
}


This ensures that memory isn't constantly allocated and not deleted. Hopefully in the future the Sun JNI examples will note this better.

1 comment:

Anonymous said...

the bahavior is normal,
you creat a string buffer and NewStringUTF creates a copy of your string ...
you should free your own buffer.

---
JNIEXPORT jstring JNICALL Java_myClass_myMethod(JNIEnv *env, jobject obj){
...
LPTSTR buffer = (LPTSTR)malloc(200*sizeof(TCHAR));
...
jstring res;
res = env->NewStringUTF(buffer);
free(buffer);
return (res);
}