Генерация интерфейса с ASM не работает

Мне нужно создать интерфейс во время выполнения. Этот интерфейс будет использоваться в динамическом прокси. Сначала я нашел эту статью в 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;
}

Я не вижу причин, почему я должен получить эту ошибку. Может ли кто-нибудь объяснить это мне?

1 ответ

Решение

Методы в интерфейсе должны быть public,

Кроме того, в вашем removeInvalidAbstractModifiers() метод, вы должны использовать |= установить флаг, а не +=, Последнее вызовет проблемы, если флаг уже установлен (что, как я понимаю, не будет, если начинать с 0, но это хорошая привычка). Хотя почему вы устанавливаете флаг в методе "удалить", я понятия не имею.

Другие вопросы по тегам