Exception stacks.
Exception in thread "main" java.lang.ClassCircularityError:
plugins/agents/Agent
at java.lang.Class.getDeclaringClass(Native Method)
at java.lang.Class.getEnclosingClass(Class.java:1085)
at java.lang.Class.getCanonicalName(Class.java:1169)
at agents.loader.AgentLoader.getPluginAgentFromCache(AgentLoader.java:288)
at compiler.AgentCompiler.main(AgentCompiler.java:365)
Below is the code which cause the error. It's very strange if I change the getCanonicalName to getName then everything is fine. These loaded classes are loaded with customized ClassLoader. like cl = defineClass(name, byteArray, 0, byteArray.length);
public Class getPluginAgentFromCache(String name)
{
if (_loadedClasses == null)
return null;
Iterator <Class> iter = _loadedClasses.iterator();
while (iter.hasNext())
{
Class c=iter.next();
if (c.getCanonicalName().equals(name))
return c;
}
return null;
}
Any one can tell me why getCanonicalName here will throw this error? (JDK 1.6.0_20)
UPDATE After some research, I find that when you define the class you must load the its parent class first. But it's hard. When I write to the binary, they are just ordered by the sequence in the file folder. So when I load them, they will not order by the class hieriarchy. It's a bit annoying here.For now I just loop the classes , then load the error class again. This is workaround but not a good one.
The reason why I hit this issue is I am trying to do something JVM not allowed. I am loading one child class using a custom classloader, but load the parent class using another classloader. This will cause issue when you call getCanonicalName, I guess this time, JVM will try to find its parent class, but it failed due to the parent class is loaded by another classloader. So this exception is thrown.
What I did to fix it, is to put all the parent class(Except the Object class:-)) and the child class to be loaded by the same classloader and interface doesn't need to be loaded by same classloader. About the loading order,
I solved it by adding a findClass method, in this method, it will look for the dependency class by this custom findClass()
method. Before calling findClass(),
i will firstly look for the dependency class by the parent classloader.
The call sequence of this classloader is custom classloader loadClass()
=> super (webapp's classloader) loadClass()
=> findClass()
method
webapp's classloader is set by the constructor of custom classloader.
So everything is resolved now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With