0 Replies Latest reply on Jul 4, 2007 8:28 AM by oglueck

    Solution for Lazy proxy class leak

    Novice

      Hi,

      It is a known problem that 4.0.4 and EJB-3 leaks Hibernate lazy proxy classes generated by Javassist. The cache introduced in Javassist-3.4 (4.0.4 ships with Javassist-3.2) should solve the problem, but unfortunately doesn't. Probably because Hibernate uses a different MethodHandler for each new proxy and so you get a cache miss.

      However it is possible to use Javassist-3.4 and supply a custom ClassLoaderProvider instance. It is important that this provide creates a new CL instance that just delegates. So the CL can be collected (and so can the proxy). Here is how to do that. The code can be put into a service mbean:

       ProxyFactory.useCache = false;
       ProxyFactory.classLoaderProvider = new ClassLoaderProvider() {
       public ClassLoader get(ProxyFactory pf) {
       ClassLoader parent = getClassLoader(pf);
       ClassLoader cl = new ClassLoader(parent) {
       @Override
       public Class loadClass(final String className) throws ClassNotFoundException {
       try {
       return super.loadClass(className);
       } catch (ClassNotFoundException e) {
       // only allow loading of ProxyObject from this loader
       if (className.equals(ProxyObject.class.getName())) {
       return ProxyObject.class.getClassLoader().loadClass(className);
       }
       // was some other classname, throw the CNFE
       throw e;
       }
       }
       };
       return cl;
       }
      
       private ClassLoader getClassLoader(ProxyFactory pf) {
       Class superClass = pf.getSuperclass();
       Class[] interfaces = pf.getInterfaces();
       ClassLoader loader = null;
       if (superClass != null && !superClass.getName().equals("java.lang.Object"))
       loader = superClass.getClassLoader();
       else if (interfaces != null && interfaces.length > 0)
       loader = interfaces[0].getClassLoader();
      
       if (loader == null) {
       loader = getClass().getClassLoader();
       // In case javassist is in the endorsed dir
       if (loader == null) {
       loader = Thread.currentThread().getContextClassLoader();
       if (loader == null)
       loader = ClassLoader.getSystemClassLoader();
       }
       }
      
       return loader;
       }
      
       };
      


      I don't know if this leak is fixed in later JBoss versions.