字节码故事——“Can I obtain parameter name from Bytecode”
字节码故事——“Can I obtain parameter name from Bytecode”
舍瓦温 发表于3年前
字节码故事——“Can I obtain parameter name from Bytecode”
  • 发表于 3年前
  • 阅读 32
  • 收藏 0
  • 点赞 0
  • 评论 0

【腾讯云】买域名送云解析+SSL证书+建站!>>>   

摘要: 需求就是这样丰富多彩,保不齐哪天,你需要从通过读取字节码中了解一个类。这看起来没什么,ASM来搞定。一切都那么顺利,直到你需要获取类中方法的参数名……

需求就是这样丰富多彩,保不齐哪天,你需要从通过读取字节码中了解一个类。这看起来没什么,ASM来搞定。一切都那么顺利,直到你需要获取类中方法的参数名……

我就是这样,今天需要为一些已经打成 jar 的类提供在线的远程方法调用,也就是要读取字节码,找出所有的方法,包括这些方法的返回值、参数名称和类型。首先想到的是翻出 ASM ,用 visitMethod。

public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if((Opcodes.ACC_PUBLIC & access)>0) {
      System.err.println("method name: " + name);
      System.err.println("return type: " + Type.getReturnType(desc));
      System.err.println("argument types: " + Arrays.toString(Type.getArgumentTypes(desc)));
    }
    return super.visitMethod(access, name, desc, signature, exceptions);
  }

然后你发现,方法名、返回值、参数类型都是有的,但是参数名称真没有, ** 因为在 bytecode 里,参数名已经消失了**!

好吧,我严谨一点说:

在JDK 8 之前,Bytecode 里真的没有方法的参数名

那 JDK 8 里就有了? 是的,但你需要在 compile 的时候加个参数

javac -parameters

添加这个参数之后,Bytecode里相当于被插入这么一行

private static final String __PARANAMER_DATA = "v1.0 \n"
      + "<init> com.example.PeopleService peopleService \n"
      + "setName java.lang.String,java.lang.String givenName,familyName \n";
      + "setDateOfBirth int,int,int day,month,year \n";

对,就是这么一个格式化的字符串,将方法的类型和名称单独赋值给了 __PARANAMER_DATA

现在你就能找到梦寐以求的方法参数名了。

如果 JDK 8 之前版本编译的 class 怎么办?其实 -parameters 这种方案来自于 paranamer。从 JDK 5.0 开始,paranamer 就可以通过在编译结果里添加 __PARANAMER_DATA 这样一个常量来达到让字节码读取者获得方法参数名的目的了。只是到 JDK 8,这个方案被“收编”了,成了 buildin 了。

所以在 JDK 8 之前版本中,如果 class 编译是可控的话,可以在 class 编译的过程使用 paranamer-generator.jar 的 API 来实现 -parameters 的效果。大概是这样

ParanamerGenerator generator = new QdoxParanamerGenerator();
generator.processSourcePath(path + "/src/test", path + "/target/test-classes/");

paranamer 也提供了 ANT、MAVEN(利用插件) 的构建支持。

一个paranamer的贡献者提供了 JavadocParanamer,可以通过读取 javadoc 来获得方法参数名。

总的来说,获取方法参数名这么件小事,却是刚需,paranamer 提供了一整套的方案来实现。

标签: paranamer bytecode
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 6
博文 13
码字总数 8280
×
舍瓦温
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: