Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating methods with generic types with Asm bytecode generator (ClassWriter)

Defining simple getters and setters is easy using Asm (and fortunately it is even explained in their FAQ). But one thing that is not mentioned, and for which I have been unable to find documentation, is how to implement these using generic type information.

I am actually able to determine generic type information itself quite easily (since code will take existing fields and/or methods and full generic type handling and resolution exists). I just need to generate generics version for types that have generic type included.

I hope this is something as easy as modifying signature Asm ClassWriter/MethodVisitor calls take, but some comments in documentation indicate it might not be that easy (as generics information is stored in bit different place than regular info).

EDIT: looks like entry point is "ClassWriter.visitField/Method(...., String signature) -- note that it's "description" that contains normal non-generic class information, but term "signature" (in JLS) specifically refers to generics-including type information.

like image 202
StaxMan Avatar asked Jul 14 '10 21:07

StaxMan


1 Answers

You can build the signature using ASM's SignatureWriter class.

For example, suppose you wish to write the signature for this method:

public <K> void doSomething(K thing)

You could use this code:

SignatureWriter signature = new SignatureWriter();
signature.visitFormalTypeParameter("K");

// Ensure that <K> extends java.lang.Object
{
    SignatureVisitor classBound = signature.visitClassBound();
    classBound.visitClassType(Type.getInternalName(Object.class));
    classBound.visitEnd();
}

// The parameter uses the <K> type variable
signature.visitParameterType().visitTypeVariable("K");

// The return type uses the void primitive ('V')
signature.visitReturnType().visitBaseType('V');

signature.visitEnd();

String signatureString = signature.toString();

Which is equivalent to:

String signatureString = "<K:Ljava/lang/Object;>(TK;)V;"
like image 123
Adam Paynter Avatar answered Oct 06 '22 21:10

Adam Paynter