文档章节

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

舍瓦温
 舍瓦温
发布于 2015/06/04 21:08
字数 659
阅读 33
收藏 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
Jvm与字节码——类的方法区模型

从一个类开始 我们从一个简单类开始说起: 这是一段平凡得不能再平凡的Java代码,稍微有点编程语言入门知识的人都能理解它表达的意思: 创建一个名为SimpleClass的类; 定义一个入口main方法...

溜达向日葵
08/31
0
0
震惊,西方的程序员跑得居然这么快

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

Kaede
2017/03/21
0
0
PHP 虚拟机 HHVM 3.26 发布,引入全新 HackC 编译器

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

局长
05/08
1K
9
语法解析器!

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

付翔
2014/12/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【Flutter教程】从零构建电商应用(一)

在这个系列中,我们将学习如何使用google的移动开发框架flutter创建一个电商应用。本文是flutter框架系列教程的第一部分,将学习如何安装Flutter开发环境并创建第一个Flutter应用,并学习Flu...

笔阁
22分钟前
5
0
什么是以太坊DAO?(三)

Decentralized Autonomous Organization,简称DAO,以太坊中重要的概念。一般翻译为去中心化的自治组织。 投票支付合约的所有费用和行动需要时间,并要求用户始终保持活跃,知情和专注。另一...

geek12345
23分钟前
2
0
一个本科学生对Linux的认知

一个本科学生对Linux的认知 我是一名大三的普通一本大学的软件工程的一名学生,学校开设了一些关于系统开发的课程,纸上得来终觉浅,学校的课程课时较短,想要在56个课时之内学会一些公司需要...

linuxCool
今天
3
0
CentOS 安装Tomcat

Tomcat 介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 Java 程序写的网站用tomcat+jdk来运...

野雪球
今天
1
0
OSChina 周四乱弹 —— 每天都迟到是种什么样的体验

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @开源中国首席机器人 :《Too Good At Goodbyes (Acoustic) - Sam Smith - 单曲》 《Too Good At Goodbyes (Acoustic) - Sam Smith - 单曲》 ...

小小编辑
今天
876
13

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部