[jboss-dev-forums] [Design the new POJO MicroContainer] - Re: Generated Classes not found if they do not match any of
kabir.khan@jboss.com
do-not-reply at jboss.com
Thu Jan 22 09:10:19 EST 2009
Actually, this is a problem for the AOP proxies, which may be in the default package when creating a proxy for something in packages starting with java. or sun.
Digging into this I found the following:
| ClassLoader loaderA = //ClassLoader belonging to DefaultDomain with package a
| ClassLoader loaderB = //ClassLoader belonging to DefaultDomain with package b
|
| //These all work
| Class<?> aA = loaderA.loadClass("a.A");
| Class<?> bB = loaderB.loadClass("b.B");
| Class<?> bA = loaderB.loadClass("a.A");
| Class<?> aB = loaderA.loadClass("b.B");
|
| //Define a new class x.X in loaderA
| CtClass clazz = poolA.makeClass("x.X"); //poolA uses loaderA
| Class<?> x = clazz.toClass(); //defined using loaderA
| Class<?> a.X = clazz.loadClass("x.X"); //works
| Class<?> bX = clazz.loadClass("x.X"); throws ClassNotFoundException
|
The call to toClass() ends up here in JBossClDelegatingClassPool
| public Class<?> toClass(ToClassInvokerPoolReference pool, CtClass cc, String classFileName, ClassLoader loader, ProtectionDomain domain) throws CannotCompileException
| {
| ...
| try
| {
| URL outputURL = new URL(tempURL.toString() + "/" + classFileName);
| //Write the classfile to the temporary url
| synchronized (tmplock)
| {
| if (trace) logger.trace(this + " " + pool + ".toClass() myloader:" + myloader + " writing bytes to " + tempURL);
| 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);
|
| if (myloader instanceof RealClassLoader)
| {
| ((RealClassLoader)myloader).clearBlackList(classFileName);
| }
|
| Class<?> clazz = myloader.loadClass(cc.getName());
| if (trace) logger.trace(this + " " + pool + " myloader:" + myloader + " created class:" + clazz);
| return clazz;
| }
| }
| catch(Exception e)
| {
| ClassFormatError cfe = new ClassFormatError("Failed to load dyn class: " + cc.getName() + " on " + this + " loader:" + myloader);
| cfe.initCause(e);
| throw cfe;
| }
| }
|
It adds the class bytes to the vfs memory context associated with loaderA.
Next it loads the class. Internally this hits the domain first, and x.X gets added to the domain's globalClassBlackList. When the class is not found in the domain, it tries the initiating loader (loaderA), which can load the class.
When we try to load the class using loaderB, it cannot find the class using loaderB since loaderB will hit the domain, and the class is in the globalClassBlackList. This should be fixable by making BaseClassLoader.clearBlackList also remove the entry from its domain's globalClassBlackList?
However, the next problem then becomes updating the domain's classLoadersByPackageName since it knows nothing about package "x". I will see if I can recreate this somehow with a test in jboss-cl, and propose a fix.
What I have mentioned so far is for the mode where everything is visble in the whole domain. There will probably be further problems with OSGi style loading since we then need to update the modules?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4204018#4204018
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4204018
More information about the jboss-dev-forums
mailing list