ClassCircularityError is thrown when getCanonicalName

扶醉桌前 提交于 2020-01-14 07:39:31

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/6790349/classcircularityerror-is-thrown-when-getcanonicalname

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!