2014-01-09 30 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和它来自的类加载器定义的! –