Search code examples
javajava-bytecode-asm

With asm how to declare a non-generic class implements generic interface


For example:

class A implements Supplier<String> {

    String get(){
        ....
    }
}

I use this code but failed:

classWriter.visit(
                V1_8,
                ACC_PUBLIC,
                "abc/A",
                null,
                parentName,
                new String[]{"java/util/function/Supplier"}
        );

These interface declareation are all failed:

java/util/function/Supplier

<T:Ljava/lang/String;>java/util/function/Supplier<T>

<T::Ljava/lang/String;>java/util/function/Supplier<T>

<T:Ljava/lang/String;>java/util/function/Supplier<TT>

<T::Ljava/lang/String;>java/util/function/Supplier<TT>


Solution

  • You can use javap to look into how javac would have compiled this class. For your signature, the value would be:

    Ljava/lang/Object;Ljava/util/function/Supplier<Ljava/lang/String;>;
    

    As a first argument, you need to provide the non-generic super class and then after the generic values. This goes as the argument that is now null, indicating a non-generic class, skipping the attribute.

    Note that generic methods require bridge methods to function. You'd need to implement both Object get() and String get() and simply delegate from the first method to the second. Mark the first method as synthetic and ACC_BRIDGE.