2

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?

4 Answers4

4

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
  • 107,573
  • 31
  • 204
  • 267
  • 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 –  Jun 13 '09 at 00:12
  • 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 Jun 13 '09 at 10:14
1

I think I was trying to do something very similar (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. :)

Community
  • 1
  • 1
StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • 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 Jul 24 '10 at 06:42
1

I'd suggest using an existing library like:

elmuerte
  • 720
  • 5
  • 21
0

Try to use spring-asm library (e.g. Type.getType(String.class))

Alessandro Dionisi
  • 2,494
  • 4
  • 33
  • 37