2015-04-17 102 views
2

我有一個項目,它有自己的類加載器。 但是我在加載一些類時遇到了一個奇怪的問題。Java動態類加載器拋出ClassNotFoundException

基本上,它是這樣的:

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

但發生的事情是,即使返回一個類時,的Class.forName(...)仍然拋出一個ClassNotFoundException的(例如,可以發現here)。

另一個信息:返回的類名稱與請求的類名稱不同。

我開始想知道它是否是JVM的安全鎖(在Oracle JVM中測試過)。

謝謝!

回答

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

} 
+0

我得出了同樣的結論https://ideone.com/XLbr6U – Dawnkeeper

+0

另請參見[here](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8 -b132/java/lang/Class.java#Class.forName%28java.lang.String%2Cboolean%2Cjava.lang.ClassLoader%29) – Dawnkeeper

+0

謝謝,夥計們。我想我將不得不改變我的架構中的東西:( – Berne

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

到目前爲止,這工作得很好。現在我將把這段代碼放在我的項目中。