JNI_OnUnload not getting called...

I can't seem to get JNI_OnUnload to get called. JNI_OnLoad gets called perfectly. Is there something special I have to do to get the "Unload" function to be invoked?
[180 byte] By [brandoneggar] at [2007-9-26 4:48:29]
# 1

That gets called when the class loader is garbage collected.

The default class loader is never garbage collected, so unless you are using your own class loader that method will never be called.

And it is possible that even your own class loaders will never be garbage collected, particularily on application exit. So it might not be called then.

jschell at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 2
Why is it when I add the following line to my Java code that JNI_OnUnload gets called?System.runFinalizerOnExit(true);
brandoneggar at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 3
More specifically, unload is called when class loader's finalize() is called. The JVM can choose never to call class loader's finalize(). By calling System.runFinalizerOnExit(true);It forces the JVM to always call finalize() when JVM terminates.
yilin at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 4

Would it be considered a JNI bug if I had a global variable in my C++ DLL code that was deallocated correctly when calling System.runFinalizersOnExit(true), but if I don't call it, the Java VM overwrites the global variable with garbage causing a crash when my DLL tries to unload itself?

brandoneggar at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 5

Even more accurately, each class loader keeps loaded native library using objects of the class ClassLoader.NativeLibrary (not a public class, a packege private static class inside ClassLoader). The unload is called in the finalize() of ClassLoader.NativeLibrary. So only when those NativeLibrary objects' finalize() are called. Since you cannot get access to those private objects inside ClassLoader, so the only sure way to get unload() called is using System.runFinalizerOnExit(true);

so that the JVM is forced to call finalize() on EVERY object if it's not called earlier.

yilin at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 6

I see... It makes sense. But since runFinalizersOnExit() is a deprecated method, isn't it bad practice to use it? I would love to find the "Correct" way to fix my problem so my global memory will stop getting trashed.

By the way, thanks for the great answers so far. It is all starting to make more sense to me :)

brandoneggar at 2007-6-29 18:38:46 > top of Java-index,Core,Core APIs...
# 7
I would think it's a bug if your global variable is changed not by your code, but by JVM.
yilin at 2007-6-29 18:38:47 > top of Java-index,Core,Core APIs...
# 8

If you just want to do some cleanup in your native lib, you can expose this native unload cleanup method as another Java native method and use Runtime.addShutdownHook() to call it before the program terminates.

You can also use System.runFinalization() in that shutdown hook if you want.

yilin at 2007-6-29 18:38:47 > top of Java-index,Core,Core APIs...
# 9

>...System.runFinalizersOnExit(true)...

There is absolutely no way to guarantee that java will call finalize(). Do not rely on it for clean up.

> ...native method and use Runtime.addShutdownHook()

The best and only guaranteed way to do this is to explicitly call your own clean up method. You can use addShutdownHook to do this.

jschell at 2007-6-29 18:38:47 > top of Java-index,Core,Core APIs...
# 10
'JNI_OnUnload' is never called by IExplore, even if 'System.runFinalizersOnExit(true);' is added to the static initializer - in this case it is only called by Appletviewer.Can anyone help me how to force a call to 'JNI_OnUnload' by IExplore?
amitro at 2007-6-29 18:38:47 > top of Java-index,Core,Core APIs...