[jboss-dev-forums] [Design of POJO Server] - Re: Classloader problem with NamingRestartUnitTestCase
adrian@jboss.org
do-not-reply at jboss.com
Tue Feb 5 15:18:10 EST 2008
"adrian at jboss.org" wrote :
| 3) There is some bad caching going on somewhere
| (the BeanInfo/ClassInfo caches are based on classloader so (1) would
| also appear as this problem).
Yep. This is the problem and it's in the JDK.
It's due to my lack of understanding of ClassLoader.findLoadedClass() actually works.
I thought this was just a cache of classes defined by this classloader
but the javadoc says it is something else
anonymous wrote :
| Returns the class with the given binary name if this loader has been recorded by the Java virtual machine as an initiating loader of a class with that binary name. Otherwise null is returned.
|
I think this is actually related to the change we made to use Class.forName()
to resolve the array class name problem in JDK6
Class.forName() does some additional caching inside the JDK.
This is what I'm seeing. The bootstrap classloader
created by conf/jboss-service.xml is remembering that it already the class
even though the classloader it loaded it from is dead:
| 2008-02-05 20:43:25,554 TRACE [org.jboss.classloader.spi.base.BaseClassLoader] BaseClassLoader at 8be9ef{vfsfile:/home/ejort/jboss-head/build/output/jboss-5.0.0.Beta4/ser
| ver/all/conf/jboss-service.xml} loadClass org.jboss.test.naming.restart.RestartNamingService resolve=false
| 2008-02-05 20:43:25,554 TRACE [org.jboss.classloader.spi.base.BaseClassLoader] BaseClassLoader at 8be9ef{vfsfile:/home/ejort/jboss-head/build/output/jboss-5.0.0.Beta4/ser
| ver/all/conf/jboss-service.xml} already loaded class org.jboss.test.naming.restart.RestartNamingService class org.jboss.test.naming.restart.RestartNamingService{cl=Bas
| eClassLoader at f834c8{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar} codeSource=(vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-rest
| art.sar <no signer certificates>)}
|
This in this code in BaseClassLoader which is supposed to be an optimization :-)
| protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
| {
| boolean trace = log.isTraceEnabled();
| if (trace)
| log.trace(this + " loadClass " + name + " resolve=" + resolve);
|
| // Validate the class name makes sense
| ClassLoaderUtils.checkClassName(name);
|
| // Did we already load this class?
| Class<?> result = findLoadedClass(name);
| if (result != null && trace)
| log.trace(this + " already loaded class " + name + " " + ClassLoaderUtils.classToString(result));
|
So the obvious fix is to replace findLoadedClass() with a real cache
of just those classes we already loaded (like it already does for resources).
The findLoadedClass() still needs to be invoked as a last resort
because of things like IBM's proxy class handling, which is actually
kind of bad because it means it will still erronously continue to return
undeployed classes until the garbage collector runs.
Or alternatively, I could just hack the problem to ignore
classes the JVM caches that have gone away. e.g.
| Class<?> result = findLoadedClass(name);
| if (result != null)
| {
| ClassLoader cl = result.getClassLoader();
| // Not us, make sure the JDK isn't caching undeployed classes
| if (cl != null && cl != this && cl instanceof RealClassLoader)
| {
| RealClassLoader rcl = (RealClassLoader) cl;
| // Ignore when undeployed
| if (rcl.isValid() == false)
| result = null;
| }
| }
|
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4126743#4126743
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4126743
More information about the jboss-dev-forums
mailing list