博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Javassist初体验
阅读量:6235 次
发布时间:2019-06-22

本文共 2177 字,大约阅读时间需要 7 分钟。

       最初接触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
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;     } }
 

转载于:https://www.cnblogs.com/asfeixue/p/4278471.html

你可能感兴趣的文章
算法笔记--二分图判定
查看>>
第二阶段冲刺 NO.3
查看>>
六个前端开发工程师必备的Web设计模式/模块资源(转)
查看>>
(转)linux下和云端通讯的例程, ubuntu和openwrt实验成功(一)
查看>>
zoj3501
查看>>
7.Python 之禅(2-11)
查看>>
mysql主从复制
查看>>
JAVA中toString方法的作用
查看>>
string.h 中常用函数
查看>>
WebService 检测到有潜在危险的 Request.Form 值
查看>>
(十五)监听器
查看>>
java多线程基本概述(三)——同步块
查看>>
caioj 1087 动态规划入门(非常规DP11:潜水员)(二维背包)
查看>>
《Linux内核设计与实现》读书笔记(十八)- 内核调试
查看>>
Vue全局判断是否登陆
查看>>
ZOJ 3927 Programming Ability Test
查看>>
HDU 5787 K-wolf Number
查看>>
c#学习笔记之基本数据类型与分支语句
查看>>
Handler类,有两个包,一个是java的,用于日志和消息,一个android,专用于消息.
查看>>
HTML5离线存储原理及实现
查看>>