2013-02-18 2 views
0

런타임에 인터페이스를 생성해야합니다. 이 인터페이스는 dynamic proxy에서 사용됩니다. 처음에는 Google에서 this article을 찾았지만 대신 ASM을 사용할 수 있음을 알았습니다. 다음은 인터페이스의 바이트 코드를 가져 오는 코드입니다.ASM을 사용한 인터페이스 생성이 작동하지 않습니다.

private static byte[] getBytecode(String internalName, String genericClassTypeSignature, Method[] methods, Class<?>... extendedInterfaces) throws IOException { 
    ClassWriter cw = new ClassWriter(0); 
    String[] interfaces = new String[extendedInterfaces.length]; 
    int i = 0; 
    for (Class<?> interfac : extendedInterfaces) { 
     interfaces[i] = interfac.getName().replace('.', '/'); 
     i++; 
    } 
    cw.visit(V1_6, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, internalName, null, "java/lang/Object", interfaces); 
    ArrayList<String> exceptions = new ArrayList<String>(); 
    for (Method m : methods) { 
     exceptions.clear(); 
     for (Class<?> exception : m.getExceptionTypes()) { 
      exceptions.add(getInternalNameOf(exception)); 
     } 
     cw.visitMethod(removeInvalidAbstractModifiers(m.getModifiers()) + ACC_ABSTRACT, m.getName(), getMethodDescriptorOf(m), getTypeSignatureOf(m), exceptions.toArray(new String[exceptions.size()])); 
    } 
    cw.visitEnd(); 
    return cw.toByteArray(); 
} 

private static int removeInvalidAbstractModifiers(int mod) { 
    int result = 0; 
    if (Modifier.isProtected(mod)) { 
     result += ACC_PROTECTED; 
    } 
    if (Modifier.isPublic(mod)) { 
     result += ACC_PUBLIC; 
    } 
    if (Modifier.isTransient(mod)) { 
     result += ACC_VARARGS; 
    } 
    return result; 
} 

JFrame을 인터페이스로 변환하려고 시도했습니다. 내 생성 된 인터페이스를로드 할 때, 그것은 나에게주는 java.lang.ClassFormatError :

java.lang.ClassFormatError: Method paramString in class javax/swing/JFrame$GeneratedInterface has illegal modifiers: 0x404 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:634) 
    // ... 

Modifier.toString(0x404)0x404protected abstract을 의미 하더군요. 내가 아는 한 클래스의 protected abstract 메소드는 완벽하게 적합합니다.

/** 
* Returns a string representation of this <code>JFrame</code>. 
* This method 
* is intended to be used only for debugging purposes, and the 
* content and format of the returned string may vary between 
* implementations. The returned string may be empty but may not 
* be <code>null</code>. 
* 
* @return a string representation of this <code>JFrame</code> 
*/ 
protected String paramString() { 
    String defaultCloseOperationString; 
    if (defaultCloseOperation == HIDE_ON_CLOSE) { 
     defaultCloseOperationString = "HIDE_ON_CLOSE"; 
    } else if (defaultCloseOperation == DISPOSE_ON_CLOSE) { 
     defaultCloseOperationString = "DISPOSE_ON_CLOSE"; 
    } else if (defaultCloseOperation == DO_NOTHING_ON_CLOSE) { 
     defaultCloseOperationString = "DO_NOTHING_ON_CLOSE"; 
    } else if (defaultCloseOperation == 3) { 
     defaultCloseOperationString = "EXIT_ON_CLOSE"; 
    } else defaultCloseOperationString = ""; 
    String rootPaneString = (rootPane != null ? 
          rootPane.toString() : ""); 
    String rootPaneCheckingEnabledString = (rootPaneCheckingEnabled ? 
              "true" : "false"); 

    return super.paramString() + 
    ",defaultCloseOperation=" + defaultCloseOperationString + 
    ",rootPane=" + rootPaneString + 
    ",rootPaneCheckingEnabled=" + rootPaneCheckingEnabledString; 
} 

나는이 오류가해야 할 이유를 볼 : 여기

JFrame에서 paramString 메서드에 대한 코드 (위 참조). 누군가 나에게 설명 할 수 있을까요?

답변

3

인터페이스의 메소드는 public이어야합니다.

또한 removeInvalidAbstractModifiers() 메서드에서 += 대신에 |=을 사용하여 플래그를 설정해야합니다. 후자는 플래그가 이미 설정되어 있으면 문제를 일으킬 것입니다 (0에서 시작하는 경우에는 표시되지 않을 것이라는 것을 알고 있지만 좋은 습관입니다). "제거"라는 메서드에서 플래그를 설정하는 이유는 무엇입니까?

+0

오, 완전히 인터페이스 메소드가 '공개'여야합니다. '| ='을 사용하여 제안 해 주셔서 감사합니다. 나는 그것이 유효한 플래그를 유지하기 때문에 "제거"메소드를 명명했습니다. 유효하지 않은 플래그를 "제거"하는 것과 거의 같습니다. 나는 ASM 4 가이드가 이유를 모르더라도'ACC_PUBLIC' ** + **'ACC_ABSTRACT'를 사용하기 때문에 처음에는 + =를 사용했습니다. 어쨌든, 고맙습니다. –

관련 문제