[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:57:59 EST 2008


"bstansberry at jboss.com" wrote : Ah, I'd missed your last post when I posted mine. Sounds like you've nailed it.

Actually, I haven't. The hack I mentioned above solves the problem
for ClassLoader.loadClass() but there is some internal caching going on with
Class.forName() where I can't intercept the behaviour fix the problem.

I added some debug to the BeanMetaDataDeployer


  |    public void deploy(DeploymentUnit unit, BeanMetaData deployment) throws DeploymentException
  |    {
  |       try
  |       {
  |          String bean = deployment.getBean();
  |          ClassLoader tcl = Thread.currentThread().getContextClassLoader();
  |          Class<?> fromClassLoader = tcl.loadClass(bean);
  |          Class<?> fromClassForName = Class.forName(bean, false, tcl);
  |          BeanInfo beanInfo = configurator.getBeanInfo(deployment);
  |          Class<?> fromBeanInfo = beanInfo.getClassInfo().getType();
  |          
  |          System.out.println("========> tcl=" + tcl + " fromClassLoader=" + printClass(fromClassLoader) + " fromClassForName=" + printClass(fromClassForName)+ " fromBeanInfo=" + printClass(fromBeanInfo)
  | 

which produces the following output on a redeploy


  | 2008-02-05 21:27:25,189 INFO  [STDOUT] ========> tcl=BaseClassLoader at 73a5d3{vfsfile:/home/ejort/jboss-head/build/output/jboss-5.0.0.Beta4/server/all/conf/jboss-service
  | .xml} fromClassLoader=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at 26f7af{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar}
  |  fromClassForName=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at 50567b{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar} fro
  | mBeanInfo=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at 50567b{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar}
  | 2008-02-05 21:27:25,191 TRACE [org.jboss.classloader.spi.base.BaseClassLoader] BaseClassLoader at 50567b{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-
  | 

@26f7af is the correct version of the classloader
@50567b is the old (undeployed) version of the classloader

The Class.forName() invocation aboves never hits the classloader
(I've checked this by looking at the TRACE logging)
so it is obviously using some cache inside the JDK.

This problem will obviously be fixed when the TCL and BeanMetaData classloader 
is set to the deployment classloader with the new code.
e.g. I can simulate this with


  |    public void deploy(DeploymentUnit unit, BeanMetaData deployment) throws DeploymentException
  |    {
  |       ClassLoader old = Thread.currentThread().getContextClassLoader();
  |       Thread.currentThread().setContextClassLoader(unit.getClassLoader());
  |       try
  |       {
  |          try
  |          {
  |             String bean = deployment.getBean();
  |             ClassLoader tcl = Thread.currentThread().getContextClassLoader();
  |             Class<?> fromClassLoader = tcl.loadClass(bean);
  |             Class<?> fromClassForName = Class.forName(bean, false, tcl);
  |             BeanInfo beanInfo = configurator.getBeanInfo(deployment);
  |             Class<?> fromBeanInfo = beanInfo.getClassInfo().getType();
  |             
  |             System.out.println("========> tcl=" + tcl + " fromClassLoader=" + printClass(fromClassLoader) + " fromClassForName=" + printClass(fromClassForName)+ " fromBeanInfo=" + printClass(fromBeanInfo));
  |          }
  |          catch (Throwable t)
  |          {
  |             throw DeploymentException.rethrowAsDeploymentException("Unexpected error", t);
  |          }
  | ...
  |       }
  |       finally
  |       {
  |          Thread.currentThread().setContextClassLoader(old);
  |       }
  |    }
  | 

And the test passes with the following output on redeploy


  | 21:40:29,591 INFO  [STDOUT] ========> tcl=BaseClassLoader at f800e1{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar} fromClassLoader=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at f800e1{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar} fromClassForName=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at f800e1{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar} fromBeanInfo=org.jboss.test.naming.restart.RestartNamingService.BaseClassLoader at f800e1{vfsfile:/home/ejort/jboss-head/testsuite/output/lib/naming-restart.sar}
  | 

This is because the initiating classloader has changed so it avoids the
Class.forName() caching problem.

But this is still going to be an issue for usage of Class.forName() from
classloaders that don't get redeployed but have initiated classloading from
redeployed classloaders.

This must also have been issue with the old UnifiedClassLoader as well?

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4126757#4126757

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4126757



More information about the jboss-dev-forums mailing list