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#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...