最初接触javassist是在研究dubbo源码的时候,那会对其的理解还停留在动态生成字节码的位置,可以做动态代理之类的动态化处理。最近由于项目需要扫描springMVC中controller层的注解,同时还需要知道方法入参的名字。基于java反射拿到注解简单,但是要拿到入参名字却需要jdk8才提供支持。但是当前项目整体环境基于jdk7,因此又想起javassist,算是get一个新技能。
基本的代码如下:
private String[] getParamName(Method method) throws Exception {
    CtClass cc = pool.get(method.getDeclaringClass().getName());     CtClass[] params = new CtClass[method.getParameterTypes().length];
    for(int i = 0; i < method.getParameterTypes().length; i++) {
        params[i] = pool.getCtClass(method.getParameterTypes()[i].getName());
    }     CtMethod cm = cc.getDeclaredMethod(method.getName(), params);     MethodInfo methodInfo = cm.getMethodInfo();
    CodeAttribute codeAttribute = methodInfo.getCodeAttribute();     LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
    String[] paramNames = new String[cm.getParameterTypes().length];
    int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
    for(int i = 0; i < attr.tableLength(); i++) {
        if(attr.index(i) >= pos && attr.index(i) < paramNames.length + pos) {
            paramNames[attr.index(i) - pos] = attr.variableName(i);
        }
    }     return paramNames;
}
 
关键的代码在于下面那个for循环。
先看看Java虚拟机规范的描述:
Java虚拟机使用局部变量表来完成方法调用时的参数传递,当一个方法被调用的时候,它的参数将会传递至从0开始的连续的局部变量表位置上。特别地,当一个实例方法被调用的时候,第0个局部变量一定是用来存储被调用的实例方法所在的对象的引用(即Java语言中的“this”关键字)。后续的其他参数将会传递至从1开始的连续的局部变量表位置上。
 

但此描述中第 0 个局部变量是指 slot 排号为 0,而不是位置为 0。

所以正确的做法就是遍历本地变量表,根据 slot 值确认是不是方法参数,体现在代码中的 API 就是 attr.index(i) 将会返回 slot。

pos 变量主要用于处理实例方法前面的 this 变量,静态方法 pos 将为 0。
ps:
目前遇到一个问题,在调试的时候偶然发现,attr.index()下标不一定按照自然增序添加。比如,0,1,2,3,5,6等。类似这样的顺序。此时,只有从小到大的顺序可以描述参数位置,因此,上述后面的部分代码修正为如下:
TreeMap<Integer, Integer> map = new TreeMap<>();
for(int i = 0; i < attr.tableLength(); i++) {
    map.put(attr.index(i), i);
}
int index = 0;
boolean flag = false;
for(Integer key : map.keySet()) {
    if (!flag) {
        flag = true;
        continue;
    }     if (index < paramNames.length) {
        paramNames[index++] = attr.variableName(map.get(key));
    } else {
        break;
    }
}
 

Javassist初体验的更多相关文章

  1. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  2. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  3. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  4. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  5. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  6. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

  7. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  8. 百度EChart3初体验

    由于项目需要在首页搞一个订单数量的走势图,经过多方查找,体验,感觉ECharts不错,封装的很细,我们只需要看自己需要那种类型的图表,搞定好自己的json数据就OK.至于说如何体现出来,官网的教程很详 ...

  9. Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验

    Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出E ...

随机推荐

  1. Cutting Sticks

    题意: l长的木棒,给出n个切割点,每切一次的费用为切得木棒的长度,完成切割的最小费用. 分析: 区间dp入门,区间dp的特点,一个大区间的解可以转换成小区间的解组合起来,每个切割点的标号代表边界. ...

  2. HDU 5749 Colmerauer 单调队列+暴力贡献

    BestCoder Round #84   1003 分析:(先奉上zimpha巨官方题解) 感悟:看到题解单调队列,秒懂如何处理每个点的范围,但是题解的一句算贡献让我纠结半天 已知一个点的up,do ...

  3. virtualbox虚拟机中mysql远程连接登陆报2003错误的解决方法

    最近在virtualbox中安装了Ubuntu 14,配置了一个mysql server,设置的桥接网络模式.在其他电脑连接的时候,总是报2003错误.开始以为是localhost没有置换为%,运行u ...

  4. DataGird导出EXCEL的几个方法

    DataGird导出EXCEL的几个方法(WebControl) using System;using System.Data;using System.Text;using System.Web;u ...

  5. 【原】Storm学习资料推荐

    4.Storm学习资料推荐 书籍: 英文: Learning Storm: Ankit Jain, Anand Nalya: 9781783981328: Amazon.com: Books Gett ...

  6. javadoc注释规范

    javadoc做注释 一. Java 文档 // 注释一行 /* ...... */ 注释若干行 /** ...... */ 注释若干行,并写入 javadoc 文档 通常这种注释的多行写法如下: / ...

  7. CORBA

    公共对象请求代理体系结构(Common Object Request Broker Architecture)

  8. JAVA虚拟机之类加载器

    转载请声明:原文转自http://www.cnblogs.com/xiezie/p/5909570.html 1.JVM的生命周期 1.1 JVM的生命周期和程序的生命周期一致 1.2 JVM结束生命 ...

  9. CentOS安装XRDP实现远程桌面访问

    1.配置环境: yum install gcc pam-devel openssl-devel -y 2.进入指定目录下载并解压xrdp: 先安装 wget; sudo yum -y install ...

  10. 第三百零五天 how can I 坚持

    今天去E世界拿抽的奖品,白去了 一趟,结果已经被拿过去了,明天还得去另一个地拿,太折腾了,今天走了1万4千多步. 哎,徐斌啊,出去见个面,这个折腾啊,受不了,想干他.开个玩笑. 黄东月,为什么打字莫名 ...