2014-01-09 5 views
0

인터페이스를 동적으로 구현해야하는 애플리케이션을 작성 중입니다. 클래스를 생성하는 것과 관련된 (명백한) 문제가 없었습니다. javap과 decompiler에서 확인했습니다.ASM과의 인터페이스 구현 : ClassCastException

문제는 클래스를 생성하고 정의하고 인스턴스화 한 후에 발생합니다. 마지막으로 구현 된 인터페이스의 유형으로 변환합니다.

ClassWriter.visit을 호출 할 때 인터페이스에 MyInterface을 추가해도 문제가되는 것은 java.lang.ClassCastException: MyGeneratedClass cannot be cast to MyInterface입니다.

다음은 void 메서드로 가득 찬 MyInterface이라는 인터페이스의 문제를 보여주는 SSCCE입니다. generatedObject.getClass().getInterfaces() 밖으로

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

인쇄 참으로 MyInterface이 구현되는 것을 보여 않습니다. 그러나 generatedObject instanceof MyInterface은 false를 반환하는데, 나는 모순을 발견합니다.

여기에서 무슨 일이 일어나고 있는지 알 수 있습니까? 어떤 도움이라도 대단히 감사하겠습니다.

답변

4

나는 새로운 클래스 로더가 MyInterface을로드 한 클래스 로더의 하위 클래스가 아니기 때문에 모든 모양이 동일 함에도 불구하고 동일하지 않은 두 개의 다른 클래스로 끝납니다. 덕분에 그것을했다

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

return (MyInterface) new ClassLoader() { 

을 변경해보십시오. 되돌아 보면 클래스가 시스템 클래스 로더에 표시되지 않는다는 것이 눈에 띄게 분명해 보입니다. 다시 한 번 감사드립니다! – Xyene

+1

기억하십시오 : 클래스는 FQCN과 클래스 로더에 의해 정의됩니다! –