-
Bug
-
Resolution: Done
-
Major
-
jboss-fuse-6.1
-
None
-
%
-
In the implementation of pax-swissbox-core org.ops4j.pax.swissbox.core.ContextClassLoaderUtils.java class doWithClassLoader() function, the TCCL is only reset if "backupClassLoader" is non null.
public static <V> V doWithClassLoader(final ClassLoader classLoader, final Callable<V> callable ) throws Exception { Thread currentThread = null; ClassLoader backupClassLoader = null; try { if( classLoader != null ) { currentThread = Thread.currentThread(); backupClassLoader = currentThread.getContextClassLoader(); currentThread.setContextClassLoader( classLoader ); } return callable.call(); } finally { if( backupClassLoader != null ) { //--> THIS IS BAD ! currentThread.setContextClassLoader( backupClassLoader ); } } }
From the JavaDoc of Thread.getContextClassLoader():
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#getContextClassLoader()
Returns:
the context ClassLoader for this Thread, or null indicating the system class loader (or, failing that, the bootstrap class loader)
It does support returning a NULL TCCL and we should reset TCCL to it's original value regardless whether it is null or not. Otherwise, in case that the "backupClassLoader " is null, it will just keep the other class loader "classLoader " as it's TCCL. Suggested code change should look like :
public static <V> V doWithClassLoader( final ClassLoader classLoader, final Callable<V> callable ) throws Exception { if (classLoader != null) { Thread currentThread = Thread.currentThread(); ClassLoader backupClassLoader = currentThread.getContextClassLoader(); currentThread.setContextClassLoader(classLoader); try { return callable.call(); } finally { currentThread.setContextClassLoader(backupClassLoader); } } else { return callable.call(); } }
Note, you might also need to take care of checking the "classLoader" to see if it is a null in order to avoid NPE if you only want to change the finally block.
In addition, the org.ops4j.pax.swissbox.core.ContextClassLoaderUtils class is compiled into many different projects as part of the bundle, such as pax-swiss-box-core-1.6.0.jar, pax-web-runtime-3.0.6.jar, pax-web-spi-3.0.6.jar, pax-web-extender-war-3.0.6.jar, pax-web-extender-whiteboard-3.0.6.jar, pax-web-jsp-3.0.6.jar.... for instance:
jluo@/apps/jboss/fuse/6.1/orig/jboss-fuse-6.1.0.redhat-379/system/org/ops4j/pax/web/pax-web-runtime/3.0.6 jluomac$ jar tvf pax-web-runtime-3.0.6.jar |grep org/ops4j/pax/swissbox/core 0 Sun Jan 12 19:36:40 GMT 2014 org/ops4j/pax/swissbox/core/ 1151 Wed Dec 26 20:02:00 GMT 2012 org/ops4j/pax/swissbox/core/BundleClassLoader$1.class 1250 Wed Dec 26 20:02:00 GMT 2012 org/ops4j/pax/swissbox/core/BundleClassLoader$EmptyEnumeration.class 4410 Wed Dec 26 20:02:00 GMT 2012 org/ops4j/pax/swissbox/core/BundleClassLoader.class 3022 Wed Dec 26 20:02:00 GMT 2012 org/ops4j/pax/swissbox/core/BundleUtils.class 1285 Wed Dec 26 20:02:00 GMT 2012 org/ops4j/pax/swissbox/core/ContextClassLoaderUtils.class
Once we fixed pax-swissbox-core bundle for the org.ops4j.pax.swissbox.core.ContextClassLoaderUtils.java class, we will need to rebuild all of those projects in order to pick up the change.