0

我需要在运行时生成一个接口。该接口将用于动态代理。起初,我从 Google 找到了这篇文章,但后来我发现我可以使用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)告诉我这0x404意味着protected abstract。据我所知,类中的protected abstract方法abstract是完全合法的。

这是paramString方法的代码(见上文)JFrame

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

我看不出为什么我应该得到这个错误。有人可以向我解释一下吗?

4

1 回答 1

3

接口中的方法必须是public.

此外,在您的removeInvalidAbstractModifiers()方法中,您应该使用|=来设置标志,而不是+=. 如果标志已经设置,后者会导致问题(我意识到如果从 0 开始就不会,但这是一个好习惯)。虽然你为什么要在一个名为“删除”的方法中设置标志,但我不知道。

于 2013-02-18T19:32:57.947 回答