[jboss-dev-forums] [Design of AOP on JBoss (Aspects/JBoss)] - Re: ClassLoading Module usage

kabir.khan@jboss.com do-not-reply at jboss.com
Thu Oct 18 07:12:03 EDT 2007


This now works locally. I've modified VFSTopLevelClassLoaderSystemDeployer to pass in the extra root


  | public class VFSTopLevelClassLoaderSystemDeployer extends AbstractTopLevelClassLoaderSystemDeployer
  | {
  |    @Override
  |    protected VFSClassLoaderPolicy createTopLevelClassLoaderPolicy(DeploymentContext context, Module module) throws Exception
  |    {
  |       ClassPathVisitor visitor = new ClassPathVisitor();
  |       context.visit(visitor);
  |       Set<VirtualFile> classPath = visitor.getClassPath();
  |       
  |       VirtualFile[] roots = new VirtualFile[classPath.size() + 1];
  |       int i = 0;
  |       for (VirtualFile path : classPath)
  |          roots[i++] = path;
  |             
  |       MemoryContextFactory factory = MemoryContextFactory.getInstance();
  |       VFSContext ctx = factory.createRoot(module.getDynamicClassRoot());
  |       
  |       URL url = new URL(module.getDynamicClassRoot() + "/classes");
  |       roots[i++] = factory.createDirectory(url).getVirtualFile();
  |       
  |       VFSClassLoaderPolicy policy = new VFSClassLoaderPolicy(roots);
  |       policy.setExportAll(module.getExportAll());
  |       policy.setImportAll(module.isImportAll());
  |       // TODO JBMICROCONT-182 more policy from "module"
  |       return policy;
  |    }
  | }
  | 

Then in the JBoss5ClassPool I do

  |    public Class toClass(CtClass cc, ClassLoader loader, ProtectionDomain domain) throws CannotCompileException
  |    {
  |       lockInCache(cc);
  |       final ClassLoader myloader = getClassLoader();
  |       if (myloader == null || tempURL == null)
  |       {
  |          return super.toClass(cc, loader, domain);
  |       }
  |       
  |       try
  |       {
  |          String classFileName = getResourceName(cc.getName());
  |          URL outputURL = new URL(tempURL.toString() + "/" + classFileName);
  |          //Write the classfile to the temporary url
  |          synchronized (tmplock)
  |          {
  |             ByteArrayOutputStream byteout = new ByteArrayOutputStream();
  |             BufferedOutputStream out = new BufferedOutputStream(byteout);
  |             out.write(cc.toBytecode());
  |             out.flush();
  |             out.close();
  |             
  |             byte[] classBytes = byteout.toByteArray();
  |             MemoryContextFactory factory = MemoryContextFactory.getInstance();
  |             factory.putFile(outputURL, classBytes);
  | 
  |             clearCacheOnLoaderHack(myloader);
  |             
  |             return myloader.loadClass(cc.getName());
  |          }
  |       }
  |       catch(Exception e)
  |       {
  |        ClassFormatError cfe = new ClassFormatError("Failed to load dyn class: " + cc.getName());
  |        cfe.initCause(e);
  |        throw cfe;
  |       }
  |    }
  |    


I had to include a hack to clear the classloader blacklist:

  |    private void clearCacheOnLoaderHack(final ClassLoader loader)
  |    {
  |       if (loader instanceof BaseClassLoader)
  |       {
  |          try
  |          {
  |             AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
  | 
  |                public Object run() throws Exception
  |                {
  |                   Class clazz = loader.getClass();
  |                   while (clazz != null && clazz != BaseClassLoader.class)
  |                   {
  |                      clazz = clazz.getSuperclass();
  |                   }
  |                   Field field = clazz.getDeclaredField("blackList");
  |                   field.setAccessible(true);
  |                   Set<String> set = (Set<String>)field.get(loader);
  |                   set.clear();
  |                   return null;
  |                }});
  |          }
  |          catch (PrivilegedActionException e)
  |          {
  |             // AutoGenerated
  |             throw new RuntimeException(e.getCause());
  |          }
  |       }
  |    }
  | 

Without clearing the black list, the new class is never picked up. Can we include a method to do this in the spi? We would not even need to clear the whole set, just a particular entry. The domain already has a method for this, but I need it on BaseClassLoader.

Another problem is if a generated AOP proxy is not in the same package as the proxied class (e.g. if the proxied super class is in the java.lang package, we create a proxy in the default package instead). This causes a problem since the underlying ClassLoaderDomain.classLoadersByPackageName does not get updated to include the default package, so the class is never found. 

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

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



More information about the jboss-dev-forums mailing list