tags:

views:

531

answers:

3

I am trying to bytecode generate a method signature from a java.lang.reflect.Method. The signature(generic type) part of it is tricky as the reflection api to get the type information and transform it into what asm needs is NOT straightforward. Know of any code out there which does this already?

A: 

I'd suggest using an existing library like:

elmuerte
+2  A: 

I am not aware of a tool that does this automatically. I would probably use the org.objectweb.asm.util.ASMifierClassVisitor class to figure out the relationship between the signatures and the ASM API calls.

For a class containing this code:

  public void foo1(Object o1, String s2) {
  }

...the tool will generate:

mv = cw.visitMethod(ACC_PUBLIC, "foo1",
     "(Ljava/lang/Object;Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 3);
mv.visitEnd();

For this code:

  public static final String[] foo2() {
    return null;
  }

...it will generate:

mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
    "foo2", "()[Ljava/lang/String;", null, null);
mv.visitCode();
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 0);
mv.visitEnd();

There are notes on method signatures in the FAQ and it helps if you understand Java class nomenclature.

Note that the ASM API can also be used to turn a java.lang.reflect.Method into an org.objectweb.asm.commons.Method. Since you can get the class from the java.lang.reflect.Method, you could use ClassVisitors / MethodVisitors to inspect the methods.

McDowell
Well I was looking for a way to get directly from the reflection api without reparsing the class file using asm. The thing gets tricky with the reflection api for Generics
OK, I think I understand - I'm not sure there would be a one-size-fits-all approach to that. If a method returns a value, you need to put some logic into it to make it valid (assuming it isn't abstract).
McDowell
A: 

I think I was trying to do something very similar (http://stackoverflow.com/questions/3250701/generating-methods-with-generic-types-with-asm-bytecode-generator-classwriter).

From class visitor's visitMethod, I can see that method like:

public List<String> foobar(List<Integer> args, List<Boolean> args2);

will produce description like:

  (Ljava/util/List;Ljava/util/List;)Ljava/util/List;

(as expected, without generics info)

and signature like:

  (Ljava/util/List<Ljava/lang/Integer;>;Ljava/util/List<Ljava/lang/Boolean;>;)Ljava/util/List<Ljava/lang/String;>;

(with generics added)

so it should be reasonably straight-forward to generate generic signature to augment non-generic description. It's pretty similar to how generics info is added in source, except for oddities introduced by handling of single-character primitive types.

I haven't tried it yet, but given that ClassWriter's visitMethod() also takes signature, I am hoping it will work. :)

StaxMan
For what it's worth, while this seemingly SHOULD work, it does not seem to. Problem is that ASM itself adds it, and can see it, but JVM's reflection methods do not seem to be find it for some reason. :-/
StaxMan