[jboss-user] [Javassist] - Problems with the tomcat classloader

Roland Käser do-not-reply at jboss.com
Thu Dec 1 14:53:50 EST 2011


Roland Käser [http://community.jboss.org/people/roli82001] created the discussion

"Problems with the tomcat classloader"

To view the discussion, visit: http://community.jboss.org/message/639418#639418

--------------------------------------------------------------
Hello 

While developing a very small and lightweight j2ee linke server, I try to extend a abstract class at runtime using: 

ClassPool pool = ClassPool.getDefault();
                              pool.insertClassPath(new ClassClassPath(this.getClass()));
                              CtClass cc = pool.makeClass("HelloWorldClientBean"); 
                              cc.setSuperclass(pool.get("ch.isn.dante.comserver.test.HelloWorldSessionBean"));

Class beanClass = cc.toClass();
cc.defrost();

Constructor constructor = beanClass.getConstructor(argsClass);

Object[] params = new Object[]{new ComServerSession(),null};   
HelloWorldSessionBean sessionBean = (HelloWorldSessionBean)constructor.newInstance(params); 
System.out.println("Hello World Output: " + sessionBean.getHelloWorld());

This works fine on the client side (regular java vm). 

On the server side I get first a very strange exception which was stangely related to the tomcats classloader. 

javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of  org/apache/catalina/loader/WebappClassLoader): attempted  duplicate class definition for name: "ch/isn/dante/comserver/test/HelloWorldSessionBeanExecutable"
javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of  org/apache/catalina/loader/WebappClassLoader): attempted  duplicate class definition for name: "ch/isn/dante/comserver/test/HelloWorldSessionBeanExecutable"
        at javassist.ClassPool.toClass(ClassPool.java:1089)
        at javassist.ClassPool.toClass(ClassPool.java:1032)
        at javassist.ClassPool.toClass(ClassPool.java:990)
        at javassist.CtClass.toClass(CtClass.java:1125)
...
Caused by: java.lang.LinkageError: loader (instance of  org/apache/catalina/loader/WebappClassLoader): attempted  duplicate class definition for name: "ch/isn/dante/comserver/test/HelloWorldSessionBeanExecutable"
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at javassist.ClassPool.toClass2(ClassPool.java:1102)
        at javassist.ClassPool.toClass(ClassPool.java:1083)



To prevent this I wrote a very ugly hack to use the system class loader and add the classpath in which this superclass:

| 
 | 
 | 
 | URL url = new File(serverServlet.getInstallDir() + "WEB-INF/classes/").toURL(); |
| 
 | 
 | 
 | URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); |
| 
 | 
 | 
 |  Class sysclass = URLClassLoader.class; |
| 
 | 
 | 
 | 
 |
| 
 | 
 | 
 |  Method method = sysclass.getDeclaredMethod("addURL", parameters); |
| 
 | 
 | 
 |  method.setAccessible(true); |
| 
 | 
 | 
 |  method.invoke(sysloader, new Object[]{url}); |
 and created the class using this modified classloader:

| 
 | 
 | Class beanClass = cc.toClass(sysloader);   | 
 | 
 | 
 |
| 
 | 
 | cc.defrost(); |


Now I get a NoSuchMethodException:

java.lang.NoSuchMethodException: HelloWorldServerBean.<init>(ch.isn.dante.comserver.server.ComServerSession, ch.isn.dante.comserver.server.ServerApplication)
        at java.lang.Class.getConstructor0(Class.java:2706)
        at java.lang.Class.getConstructor(Class.java:1657)
        at ch.isn.dante.comserver.server.ComServerSession.loadClass(ComServerSession.java:239)
        at ch.isn.dante.comserver.server.ComServer.doGet(ComServer.java:286)
        at ch.isn.dante.comserver.server.ComServer.doPost(ComServer.java:417)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

I can't see from which this error comes. When I  inspect the newly created class I get one constructor:

public HelloWorldClientBean(ch.isn.dante.comserver.server.ComServerSession,ch.isn.dante.comserver.server.ServerApplication)
--------------------------------------------------------------

Reply to this message by going to Community
[http://community.jboss.org/message/639418#639418]

Start a new discussion in Javassist at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2062]

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jboss-user/attachments/20111201/7712e565/attachment-0001.html 


More information about the jboss-user mailing list