getCanonicalName抛出ClassCircularityError

时间:2011-07-22 12:57:57

标签: java classloader

异常堆栈。

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)

以下是导致错误的代码。如果我将getCanonicalName更改为getName然后一切都很好,这很奇怪。这些加载的类加载了自定义的ClassLoader。比如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;        
}

任何人都可以告诉我为什么这里的getCanonicalName会抛出这个错误? (JDK 1.6.0_20)

更新 经过一些研究,我发现在定义类时,必须首先加载其父类。但这很难。当我写二进制文件时,它们只是被订购了 按文件夹中的顺序排列。因此,当我加载它们时,它们不会被课程命令 hieriarchy。这里有点烦人。现在我只是循环这些类,然后再次加载错误类。这是解决方法,但不是一个好的。

1 个答案:

答案 0 :(得分:2)

我遇到这个问题的原因是我试图做一些不允许JVM的事情。 我使用自定义类加载器加载一个子类,但使用另一个类加载器加载父类。当你调用getCanonicalName时会出现问题,我猜这次,JVM会 尝试找到它的父类,但由于父类被另一个类加载器加载而失败。 所以抛出了这个异常。

我所做的是修复它,将所有父类(Object类:-)除外)和子类加载到同一个类加载器中,并且接口不需要由同一个类加载器加载。关于装货单, 我通过添加一个findClass方法来解决它,在这个方法中,它将通过这个自定义findClass()方法查找依赖类。在调用findClass(),之前,我将首先通过父类加载器查找依赖类。

此类加载器的调用序列是自定义类加载器loadClass() =&gt; super(webapp的类加载器)loadClass() =&gt; findClass()方法 webapp的类加载器由自定义类加载器的构造函数设置。

所以现在一切都解决了。