2014-01-09 65 views
0

我正在編寫一個需要動態實現接口的應用程序。關於生成類我沒有(明顯的)問題:我用javap和反編譯器對它進行了驗證。使用ASM實現接口:ClassCastException

問題是,在我生成我定義和實例化的類之後。最後,我將它轉換爲實現的接口的類型。

問題是我正在用java.lang.ClassCastException: MyGeneratedClass cannot be cast to MyInterface命中,雖然我在我打電話ClassWriter.visit時添加了MyInterface作爲接口。

下面是一個SSCCE,演示了一個名爲MyInterface的接口,該接口充滿了無效方法。

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); 

cw.visit(V1_6, 
     ACC_PUBLIC | ACC_SUPER, 
     "MyGeneratedClass", 
     null, 
     "java/lang/Object", 
     new String[]{MyInterface.class.getName().replace(".", "/"}); 

{ 
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 
    mv.visitVarInsn(ALOAD, 0); 
    mv.visitMethodInsn(INVOKESPECIAL, 
      "java/lang/Object", 
      "<init>", 
      "()V"); 
    mv.visitInsn(RETURN); 
    mv.visitMaxs(0, 0); 
    mv.visitEnd(); 
} 

for (Method call : MyInterface.class.getDeclaredMethods()) { 
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, call.getName(), Type.getMethodDescriptor(call), null, null); 
    // ... 
    mv.visitInsn(RETURN); 
    mv.visitMaxs(0, 0); 
    mv.visitEnd(); 
} 
cw.visitEnd(); 
byte[] raw = cw.toByteArray(); 

try { 
    return (MyInterface) new ClassLoader() { 
     public Class defineClass(byte[] bytes) { 
      return super.defineClass("MyGeneratedClass", bytes, 0, bytes.length); 
     } 
    }.defineClass(raw).newInstance(); 
} catch (InstantiationException | IllegalAccessException e) { 
    e.printStackTrace(); 
    return null; 
} 

打印出generatedObject.getClass().getInterfaces()確實表明MyInterface實現。但generatedObject instanceof MyInterface返回false,我發現一個矛盾。

任何人都可以在這裏發生什麼?任何幫助將不勝感激。

回答

4

我想這是因爲新的類加載器不是加載了MyInterface的類加載器的子代,這意味着最終會出現兩個不同的類,儘管它們的外觀完全相同,但它們並不相同。嘗試改變

return (MyInterface) new ClassLoader() { 

return (MyInterface) new ClassLoader(MyInterface.class.getClassLoader()) { 
+0

也做到了,謝謝。回顧一下,似乎顯而易見的是,該類對於系統類加載器來說是不可見的。再次感謝! – Xyene

+1

記住:一個類是由它的FQCN和它來自的類加載器定義的! –