perils of url class loader

Download Perils Of Url Class Loader

If you can't read please download the document

Upload: kaniska-mandal

Post on 20-May-2015

1.118 views

Category:

Documents


0 download

TRANSCRIPT

  • 1. Its a very common programming technique to create any number ofURLClassLoader instances repeatedly in order to load the newimplementation of the classes/resources from the same location with the helpof new class loader instances.In fact, some well-known tools like plexus-compiler jar makes heavy usage ofIsolatedClassLoader to implement the above concept.Lets focus on the actual problem.We have a large maven project which has 200 jars in maven repo.Any code change in source file fires MavenBuilder ..- which invokes JavacCompiler (plexus-compiler jar)- in turn creates IsolatedClassLoader cl = new IsolatedClassLoader()[extends URLClassloader] ..- adds the list of 200 jars in urlClassPath - cl.addURL(URL)- loads javac.Main along with all jars in classpath and reflectively firescompilation.So for N save-operations, N instances of IsolatedClassloaders arecreated.In principle, once the application clears all references to a loader object, thegarbage collector and finalization mechanisms will eventually ensure that allresources (such as the JarFile objects) are released and closed.But in reality, the application goes OutOfMemory !We used optimal concurrent gc strategy - Xgcpolicy:optavgpause.But still the app running out of memory very quickly.Then Heap dump analysis showed there are some 100 instances (Uuh !) ofisolated class loaders each of which is holding onto unclaimedZipFileIndexEntries(.. guess what .. indexEntry for all the jars loaded on eachinstance of class laoder..)Well ! looks like.. since a new URL Class Loader is created before closing theresources in previous loader, GC is confused and does not reclaim theprevious class loader ! This causes problems for applications which need tobe able to GC in a predictable and timely fashion. It is a particular problem onWindows, because open files cannot be deleted or replaced.So are we missing something trivial here ? Is plexus-jar doing somethingwrong ?A BIG Emphatic YES !We can use sun.misc.ClassLoaderUtil to release an url class loader and fileresources held therein.

2. Lets now fix the issue.org.codehaus.plexus.compiler.javac.JavacCompiler#compileInProcess(..) {IsolatedClassLoader loader= new IsolatedClassLoader();loader.addURL(jarListoURI().toURL())c = loader.loadClass( "com.sun.tools.javac.Main" );ok = (Integer) compile.invoke(args)//Now that you are done with compilation, get rid of loader ..*** loader.close () Or sun.misc.ClassLoaderUtil.releaseLoader(loader)////// -> allows graceful release of loader and all resources*** Thankfully JDK 7 URLClassloader has implemented close() method to give the caller a chance to invalidate the loader, so that no new classescan be loaded from it. It also closes any JAR files that were opened by theloader. This allows the application to properly delete or replace these filesand, gracefully create new loaders using new implementations.The bottom line is wherever we create seemingly harmless URlCLassloaderin a repeated manner (say to generate / compile code) holding onto a goodmany jars in url classpath; we should always close the loader instance.