Archive for October, 2010

Forcing garbage collection.

First, why do you want to force the garbage collection? According to me, you probably never need to do it !
So we should never do it, but then, why do I implement it ?  Well, in my case , it makes sense :)
Ok, the title of the article is misleading you. I am not really able to force the garbage collection, but I am able to detect when the garbage collection works.
At work, we are developing an application server. It allows to dynamically add applications, and of course also allows to uninstall it, more or less as any other application server.
But even for this, you do not need to force the garbage collection; yes and no.
The problems come when you are installing code requiring some JNI libraries.
JNI implementation has some limitations that makes the loaded DLL highly linked with the current Class Loader.

It means that if you do the following steps :

  • Deploy an application which uses a dll
  • Undeploy this application
  • And deploy it again

You will get a UnsatisfiedLinkError with the message : Native Library already loaded in another classloader.
This is weird (IMHO) ! Once a DLL has been loaded, you cannot load it until the ClassLoader object has been reclaimed by the garbage collection.
Let’s check the JVM code to see how it is working.

First when you load a library, the loadLibrary code checks if the dll is not already loaded.
Let’s check the code of java.lang.ClassLoader.loadLibrary code.

private static boolean loadLibrary0(Class fromClass, final File file) {
  …
  synchronized (loadedLibraryNames) {
    if (loadedLibraryNames.contains(name)) {
      throw new UnsatisfiedLinkError ("Native Library " +
      name + " already loaded in another classloader");
    };
  …
}

As you can see, it is checking the list of loaded libraries, if the library is already associated with an otherclassloader. If it is, the load will fail.
Only when the ClassLoader.finalize is called, you will be able to load the library again.

protected void finalize() {
  ...
  for (int i = 0; i < size; i++) {
    if (name.equals(loadedLibraryNames.elementAt(i))) {
    loadedLibraryNames.removeElementAt(i);
    break;
  }
  ...
}

Then, how can we force the garbage collection to allow the finalized to be run, or at least how do we know when the class loader has been completely finalized.

During my experiments, I try just to call the method “System.gc”
It does work, but it is unpredictable. I sometimes need to call it twice, or even more. It is really not easy to be sure that the garbage collection has been executed.
I therefore developed this small piece of code:

    public static void waitGc( long timeout ) {
    	final boolean[] wait = new boolean[1];
    	
    	@SuppressWarnings("unused")
    	// create a small graph of object
        Object graph = new Object() {
    	    private Object leaf = new Object() {
	    	    protected void finalize() throws Throwable {
	    	    	synchronized( wait ) {
	    	    		logger.finest("leaf finalize called");
	    	    		wait[0] = true;
	    	    		wait.notify();
	    	    	}
	    	    }
    		};
    	    protected void finalize() throws Throwable {
    	    	logger.finest("graph finalize called");
    	    }
    	};
    	long start = System.currentTimeMillis();
    	graph = null;
    	while ( System.currentTimeMillis() < start + timeout ) {
    		// defer a little bit the gc
    		try {
    			if ( wait[0] ) {
    				logger.finest("finalize Called on object graph, gc has been executed");
    				break;
    			}
			System.gc();
			System.runFinalization(); 
			logger.finest("finalize not (yet) called");
    			synchronized( wait ) {
				wait.wait(timeout / 10);
    			}
		} catch (InterruptedException e) {
			// do not care 
		}
    	}
    }

The code is not really easy to understand. Here is how it works.
First I create an object graph, two objects which hold a reference to another object.
These objects have been singly modified to notify when the object are finalized.
The rest of the code is a simple loop, which runs System.gc and System.runFinization until it receives the notification that the object graph has been finalized.
For more security, the code does not wait indefinitely, but only for a predefined time.

Inside the container we do two things:

  • When a application is undeployed, we check if it has loaded some dynamic library
  • If not, we just undeploy it. If yes, we wait until the ClassLoader has been finalized using the same technique than above.

Even if the System.gc does nothing, we will be notified that the ClassLoader is not yet finalized, and return to the user a message stating that the component has been undeployed. But for some reasons, which will probably a memory leak on the application, the loaded dynamic library is not released yet.

Do not forget that there are some jvm options which disable the System.gc() calls.

-XX:-DisableExplicitGCDisable calls to System.gc(), JVM still performs garbage collection when necessary.

In a next article
I will explain  how to dig into the native library info, which is not available by any public way.  In that purpose, I will use a class that you probably do not know, sun.misc.Unsafe the modern java peek and poke library!