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 に答える