13

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.

starblue
  • 55,348
  • 14
  • 97
  • 151
StaxMan
  • 113,358
  • 34
  • 211
  • 239

2 Answers2

9

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;"
Adam Paynter
  • 46,244
  • 33
  • 149
  • 164
  • This is useful, thanks. My specific problem right now seems to be that resulting signature is somehow not properly written in class file, although I use correct format (as far as I know). But maybe I should double-check with SignatureWriter to make sure... – StaxMan Jul 29 '10 at 22:03
  • 2
    @StaxMan: I have had my share of trouble with it too. Perhaps this article will help: [Classworking toolkit: Generics with ASM](http://www.ibm.com/developerworks/java/library/j-cwt02076.html) – Adam Paynter Jul 29 '10 at 22:07
  • Ah! I FINALLY found the real problem in my code: I had argument V1_2 in ClassVisitor.visit(); and this needs to be V1_5 or above for generics (and annotations) to be supported. Thanks for your help! – StaxMan Jul 30 '10 at 06:25
  • @StaxMan: You're welcome! Wow, was there any particular reason why you were using version 1.2? I have never seen that level of dedication for supporting the elderly virtual machines. :) – Adam Paynter Jul 30 '10 at 10:58
  • No, not at all, it just probably came from some legacy code. It definitely was not explicitly chosen; package itself (that uses ASM) requires 1.5 anyway, and soon 1.6 probably. – StaxMan Jul 31 '10 at 03:46
-2

In my experience most on-the-fly bytecode generation libraries don't have good support for generic types; however erased classes work just fine (unless you want to introspect those classes later, of course).

Tassos Bassoukos
  • 16,017
  • 2
  • 36
  • 40
  • 1
    Unfortunately I specifically do need introspection -- that is how using library will actually construct serializers and deserializers. :-/ Yes, codewise erasure would work ok... and I may have to just find another way to make things work, perhaps by adding new kinds of annotations to effectively replicate signatures. – StaxMan Jul 28 '10 at 02:03