JNI: NewGlobalRef/NewWeakGlobalRef

399 views
Skip to first unread message

joel

unread,
Mar 23, 2009, 4:22:23 PM3/23/09
to android-platform
I'm not clear on what I think is supposed to be workaround for the
lack of NewWeakGlobalRef() support in Dalvik; dalvik/docs/jni-
tips.html states that java.io.FileDescriptor shows how to cache class
IDs, by making a static "nativeClassInit()" which is called in the
class static initializer, which will create a global reference to the
class on the native side.

As I understand it though, global references to a class prevent the
garbage collection of that class, and if the class is never garbage
collected then the classloader for that class will never be collected,
and the native lib will never be unloaded. Quoting
http://java.sun.com/docs/books/jni/html/other.html#30440 :

"We are now ready to explain why we cache the C class in a weak global
reference instead of a global reference. A global reference would keep
C alive, which in turn would keep C's class loader alive. Given that
the native library is associated with C's class loader L, the native
library would not be unloaded and JNI_OnUnload would not be called."

Looking at dalvik/libcore/luni/src/main/native/
java_io_FileDescriptor.c, it seems like that code is guilty of this
mistake, because it is creating a strong global reference which is
never deleted? But I must be missing something...

Dan Bornstein

unread,
Mar 23, 2009, 4:38:13 PM3/23/09
to android-platform
On Mon, Mar 23, 2009 at 1:22 PM, joel <joe...@gmail.com> wrote:
> Looking at dalvik/libcore/luni/src/main/native/
> java_io_FileDescriptor.c, it seems like that code is guilty of this
> mistake, because it is creating a strong global reference which is
> never deleted? But I must be missing something...

The main thing you are missing in this case is that
java.io.FileDescriptor is a class that is on the boot classpath.
Pretty much by definition, no classes on the boot classpath can ever
be collected (since every thread has a reference to it, though
possibly indirectly), so there's no point in trying to arrange for
that possibility.

Also (and Fadden might correct me on this) the current VM
implementation doesn't collect classes in general, even in cases where
it is allowed to.

As yet, this hasn't been a problem for the system, probably because
there aren't many (any?) apps which try to load an unbounded number of
classes. I suspect that such a case will eventually arise, though.

-dan

joel

unread,
Mar 23, 2009, 5:05:15 PM3/23/09
to android-platform
Thanks Dan. Then although it's not an issue for
java.io.FileDescriptor, it seems there isn't a solution for an
arbitrary JNI lib not associated with a class on the boot classpath?

That's sort of contrary to what jni-tips.html is saying:

"If you would like to cache the IDs when a class is loaded, and
automatically re-cache them if the class is ever unloaded and
reloaded, the correct way to initialize the IDs is to add a piece of
code that looks like this to the appropriate class: <goes on to
discuss nativeClassInit() and FileDescriptor as an example>"

whereas if you follow the FileDescriptor example, your class will
never be unloaded/reloaded anyway, right?

Cheers to whoever is working on NewWeakGlobalRef() support. I wonder
how long it takes to get class/field/method reference/IDs, maybe it's
not a big performance hit and I can just remove the code which caches
them...

joel

unread,
Mar 23, 2009, 5:10:09 PM3/23/09
to android-platform
The other option is to go ahead and use NewGlobalRef(), since as you
pointed out, GCing classes may not be necessary (or even supported). I
was afraid this would prevent clean shutdown of a process using such a
library, but maybe not? Certainly JNI_OnUnload() will never be called,
so you can't rely on that for cleanup.

Dan Bornstein

unread,
Mar 23, 2009, 5:14:48 PM3/23/09
to android-platform
On Mar 23, 2:10 pm, joel <joe...@gmail.com> wrote:
> The other option is to go ahead and use NewGlobalRef(), since as you
> pointed out, GCing classes may not be necessary (or even supported). I
> was afraid this would prevent clean shutdown of a process using such a
> library, but maybe not? Certainly JNI_OnUnload() will never be called,
> so you can't rely on that for cleanup.

My default advice would be to plan for the possibility of class
unloading, as I expect we *will* have it at some point. However, since
we also don't have JNI weak globalrefs, there's not much you could do.

So, yeah, I would just use NewGlobalRef() and be done with it (for now
at least). This won't prevent the VM from shutting down cleanly;
there's no rule about dropping global refs before shutdown or anything
like that (just like there's no rule that all objects must become
garbage before the VM exits). The only "hazard" is that in a future
incarnation of the platform, your code might use more memory than it
strictly needs to.

-dan
Reply all
Reply to author
Forward
0 new messages