[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