Local/Global objects and Garbage Collection

Hi there,

I am working a project which is going to allow some legacy C code run in our "new" Java process. In doing the preliminary work I have come into a slight problem that I can't quite get my head around, hopefully; someone here can set me on the right path.

I did searches but didn't find anything that helpful. If there is a FAQ or a post I missed please point me in that direction.

So basically the C code uses some wrapper structs and function pointers. for example we have a string 'class' which is something like this:

typedef struct _stringClass {

void* hdl;

stringFT ft;

} stringClass;

The stringFT performs basic functions, for example 'getCharPointer' which returns a 'const char*' to the underlying array. The problem I am having is two fold

1a - We have a global function 'stringClass createNewString(const char* str)', but the existing code does not have a 'release' type function (our existing C product uses Garbage Collection internally to free the memory). So the question becomes, when the 'createXX' function is called and I use 'NewStringUTF' do I need to worry about someone calling a 'release' type function to let the JVM know it is ok to free the memory.

1b - I guess this also brings up the question of local refs and global refs. Since this 'createXX' function is being called by a C shared object, do I need call 'NewGlobalRef' before returning it to the caller?

2 - As I mentioned about one of the function returns a 'const char*' of the string. Basically the same issue here, as I can call 'GetStringUTFChars' to get the "const char*", but there is no way for me to call 'ReleaseStringUTFChars' to let the JVM know it is no longer in use. Any thoughts on this? The only thing I can think of is to copy the string returned from 'GetStringUTFChars' but that ends up in a memory leak as well since the caller is not required to call free or release on the returned 'const char*'

Just to give you an overview of the call process this is what happens:

1 JVM loads the JNI module I am writing.

2 JVM calls the JNI methods

3 JNI methods loads a separate shared object containing the legacy code.

4 JNI methods call routine in the legacy code.

5 Legacy code uses the wrapper 'classes' we have to create objects.

6 Legacy code returns these wrapper 'classes' back to the JNI code

7 JNI code converts* the wrapper 'classes' into java objects and returns them.

* by "convert" I basically mean they take the java object stored in the 'hdl' member and return it to the JVM. Also these object are not always returned to the JNI code (e.g. the legacy code might create a temp object).

I know this is probably clear as mud, I've tried to explain it as best I can. If you have any thoughts or comments let me know.

Thanks

[2922 byte] By [jim.marshalla] at [2007-10-3 8:43:57]
# 1

I'm confused by your description.

Specifically, you discuss returning the "hdl" member to java.

Of course hdl is a void*, so what happens? Is this in fact turned into astring? Or does it point to a string? Or is it in fact a pointer to a jobject - something already instantiated in java?

And you talk about "returning" this to java. How? Is some java object the return value for the native method call (from the java side) or what?

Finally: If your code creates a java object, and somehow passes that java object to some class in the JVM, then that class will be garage collected when the last reference disappears - no need to do any releasing yourself.

bschauwejavaa at 2007-7-15 3:52:41 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

I'm not surprised that you are confused, I am also ;)

Anyway, I think I figured out my confusion today. I was reading the docs incorrectly. I thought that the documentation was stating that when you call 'NewObject' you got a local reference which was only valid for the function you where in, for example

jobject foo(JNIEnv* env)

{

jobject doo = env->NewObject(...);

....

return doo;

}

I mis-interpreted the docs as saying that once foo exited the 'doo' object was eligible for GC and that I would have to call 'NewGlobalRef' if I wanted it to persist past the foo function. My understanding is now that the local ref (created by NewObject) will be fine until the native method returns to the JVM.

anyway to answer your questions. The 'hdl' would be some jobject (either an object created with 'NewObject' or a jstring created with 'NewStrinbgUTF').

Yes the return value of the native method is a Java object (e.g. String).

Thanks, I think I've figured out what I was missing.

-Jim

jim.marshalla at 2007-7-15 3:52:41 > top of Java-index,Java HotSpot Virtual Machine,Specifications...