文档章节

字节码故事——“Can I obtain parameter name from Bytecode”

舍瓦温
 舍瓦温
发布于 2015/06/04 21:08
字数 659
阅读 33
收藏 0
点赞 0
评论 0

需求就是这样丰富多彩,保不齐哪天,你需要从通过读取字节码中了解一个类。这看起来没什么,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 提供了一整套的方案来实现。

© 著作权归作者所有

共有 人打赏支持
舍瓦温
粉丝 6
博文 14
码字总数 8280
作品 0
呼和浩特
程序员
深入字节码 -- 玩转 ASM-Bytecode

本文是《深入字节码 -- 使用 ASM 实现 AOP》的后续博文。在上一篇文章中介绍了如何使用 ASM 动态安插代码到类中,从而简单实现 Aop。文章得到了广大朋友好评,我也希望可以不负众望继续写出可...

哈库纳
2013/09/23
0
0
震惊,西方的程序员跑得居然这么快

昨天刚刚发表了一篇文章(ProGuard又搞了个大新闻),主要吐槽的是项目里面使用ProGuard工具导致的一个诡异的坑。其中根本的原因就是,ProGuard混淆Java注解类的时候,把两个方法混淆成同样的...

Kaede
2017/03/21
0
0
语法解析器!

举例:将i = a + b * c作为源代码输入到解析器里,则广义上的解析器的工作流程如下图: acc -= 3; iconst_2iaddistore_0 add eax, 2 } // a[0]aload_1iconst_0 // 右子树:加法// aiload_2//...

付翔
2014/12/08
0
0
用 Python 编写的 Python 解释器

(点击上方公众号,可快速关注) 翻译: qingyunha 英文:Allison Kaptur http://qingyunha.github.io/taotao/ Allison是Dropbox的工程师,在那里她维护着世界上最大的由Python客户组成的网络...

Python开发者
04/22
0
0
PHP 虚拟机 HHVM 3.26 发布,引入全新 HackC 编译器

HHVM 3.26 已发布,值得关注的更新有: Hack 编译器 —— HackC typechecker 的重新授权以及相关工具和库采用 MIT 开源协议 对 Ubuntu 18.04 的支持 开发团队表示,在历经一年多的开发后,现...

局长
05/08
0
0
《字符串连接你用+还是用StringBuilder》续

前言 前面的一篇文章《字符串连接你用+还是用StringBuilder》,有朋友找我反馈了一些问题,其中一位朋友说JDK10下生成的字节码跟文章中并不一样,这里继续看下是什么情况。 问题描述 如下图,...

超人汪小建
前天
0
0
Spring/Boot/Cloud系列知识(3)——代理模式(中)

(接上文《Spring/Boot/Cloud系列知识(2)——代理模式》) 2.2、代理模式在Spring中的应用 那么java中基于java.lang.reflect.Proxy的动态代理模式和Spring生态有什么关系呢?Spring中的所有...

yinwenjie
2017/09/17
0
0
深入理解JAVA虚拟机学习笔记12——Class类文件的结构(4属性)

我们的口号是:每天进步一点点! 上一篇的字段写到属性的时候,由于属性涉及到的内容比较多,我们暂时搁置了,这一篇是Class文件结构的最后一篇,我们就详细说说属性表结合。 九、属性(Att...

徐可心
06/11
0
0
python解析器--版本--IDE环境

-- --python 版本---解析器---------------------------------------------------------------------------- -- --5-----------Python 工具-------------数据专家必知必会的 7 款 Python 工具......

liapple6
2017/12/26
0
0
Java泛型-类型擦除

一、概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变),奇怪的ClassCastException等。 正确的使用Java泛型需要深入的了...

lwwjing
2016/03/17
50
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

jquery获取当前日期并且格式化

1.制定Format规则 //时间格式化问题Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 ......

gulf
7分钟前
0
0
Spring5(Java8版本)中的反射工具类和注解工具类

1.反射工具类 学习反射时很好的反射教程.这个工具类是基于Java8的。 package org.springframework.util;import java.lang.reflect.Constructor;import java.lang.reflect.Field;imp...

hutaishi
8分钟前
0
0
java io

Java IO在实际开发中的应用 http://www.cnblogs.com/ldh-better/p/7158658.html

小鱼吃大鱼
8分钟前
0
0
初结 react(当 React 版本是 ^16.2.0,当前时间 2018-01-12)

最近一段时间在零零碎碎地看 react 。在此,向所有自学 react 的朋友点个赞。多说一句,在自学道路上一定要戒骄戒躁,坚持下来。-----因为自学过程真的是心累啊(不同版本的博客不同的说法)...

秋季长青
9分钟前
7
0
grub2要启动整个iso的菜单命令如下

grub2要启动整个iso的菜单命令如下 menuentry "启动 Deepin OS Live System" --class deepin { set isofile=/DeepinOS.iso search -f --no-floppy --set=root $isofile set gfxpayload=keep ......

ziluopao
16分钟前
1
0
vue如何使用富文本编辑器wangEditor及图片上传

html定义一个装编辑器的DIV <template> <div id="editor"></div></template> npm安装wangEditor npm install wangeditor --save /*wangeditor需要小写*/ vue页面导入wangEditor im......

心鑫
19分钟前
0
0
乐观锁

最近公司一个项目中会遇到一个用户记录被多次插入的情况。其实在保存之前先判断有没有的。 觉得可以采用乐观锁机制来解决问题。 JPA之@Version进行乐观锁并发更新 使用JPA实现乐观锁 spring...

miaojiangmin
22分钟前
1
0
flowable 清除流程部署缓存

flowable 或者activity 修改流程图后 需要重启服务器。此文档可解决不用重启服务器,直接干货 public class DeploymentCacheCmd implements Command<Deployment>, Serializable { priv...

装死的乌龟
27分钟前
0
1
安装APK报错 INSTALL_FAILED_TEST_ONLY终极解决方案

1、检查\app\src\main\AndroidMainfest.xml中是否有testOnly属性为true,如果有去掉或者改为false 2、检查Android Studio和gradle版本是否为alpha版本,换为稳定版本 3、检查是否关闭Instant...

harukong
30分钟前
0
0
并发插入引发的死锁问题排查

一.业务背景 我们现在的业务是一款数据产品,有不少实时计算和爬取来的数据都汇总到大数据仓库、数据挖掘平台ODPS上。然后应用在读取这些数据时,这些数据会先导入到并发读能力更强,适合结构...

tantexian
32分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部