【问题标题】:Java Dynamic classloader throws ClassNotFoundExceptionJava 动态类加载器抛出 ClassNotFoundException
【发布时间】:2015-04-17 01:40:27
【问题描述】:

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

基本上是这样的:

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

但是发生的情况是,即使返回一个类,Class.forName(...) 仍然会抛出 ClassNotFoundException(示例可以在 here 找到) .

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

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

谢谢!

【问题讨论】:

    标签: java classloader


    【解决方案1】:

    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));
    
    }
    

    【讨论】:

    • 另见here
    • 谢谢,伙计们。我想我将不得不改变我的架构中的一些东西:(
    【解决方案2】:

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

    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());
        }
    }
    

    到目前为止,这很好用。现在我将把这段代码放到我的项目中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多