Java Dynamic类加载器抛出ClassNotFoundException

时间:2015-04-17 01:40:28

标签: java classloader

我有一个拥有自己的类加载器的项目。 但是在加载某些类时我遇到了一个奇怪的问题。

基本上,它就像:

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
    // do some magic
    return myBrandNewClas;
}

但是,即使返回一个类, Class.forName(...)仍会抛出 ClassNotFoundException (可以找到示例{{3} })。

另一个信息:返回的类名称与请求的类名称不同。

我开始想知道它是否是JVM的安全锁(在Oracle JVM中测试过)。

谢谢!

2 个答案:

答案 0 :(得分:3)

forName的代码是原生的,因此很难看到,但是我会说这个名称已被选中,因为传递正确的名称有效:

public class BBB
{
public static class a {

}

private static class MyCL extends ClassLoader
{
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        System.out.println("Hi, " + a.class.getName());
        return a.class;
    }
}

public static void main(String[] args) throws ClassNotFoundException
{
    MyCL cl = new MyCL();

    System.out.println(Class.forName("com.asg.util.BBB$a", true, cl));

}

答案 1 :(得分:0)

我可以通过将类重命名为所需的类名来解决问题。

import javassist.ClassPool;
import javassist.CtClass;


public class AAA
{
    public static class B
    {
        @Override
        public String toString()
        {
            return "B";
        }
    }

    private static class X extends ClassLoader
    {
        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
        {
            try
            {
                if ("A".equals(name))
                {
                    ClassPool cp = ClassPool.getDefault();
                    CtClass clazz = cp.get("AAA$B");

                    clazz.setName("A");
                    return clazz.toClass();
                }

                return super.loadClass(name, resolve);
            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) throws Exception
    {
        X x = new X();
        System.out.println(Class.forName("A", true, x).newInstance().toString());
    }
}

到目前为止这种方法效果很好。现在我将这段代码放在我的项目中。