偶现的方法执行慢,咱们是能够用jstack捕捉到的,可是慢到什么地步倒是不必定知道的,如今就须要在不重启应用的状况下,获取方法执行的时间。java
想要打印出时间,起码想到的是aop的方式。常规的方法是必须重启应用才能加的,典型的就是spring的aop,若是容许修改代码的话可使用动态代理,或者本身写死到代码里。git
这种状况对代码的入侵过高了,若是要去掉这个功能,修改代码也是很麻烦的。github
这个须要依赖spring框架来作。能够不修改代码,可是不能作到动态生效。spring
javaagent在1.6以后可使用远程attach的方式,进行类的从新转化。这个是知足需求的。这个不了解的话能够去网上查查看。api
方式选择好之后,那么关键点就是如何选择修改字节码的框架。框架
javassist是相对好用的,不过他想要在一个方法先后加代码,是经过方法包装来的,就是命名一个新的方法名和如今执行的方法名同样,而后把旧的方法从新命名。流程以下: 转化前:代理
public void hello(){ int a=0; }
转化后code
public void hello(){ xxx helloxx(); xxx } public void helloxx(){ int a=0; }
这种状况是transform的作法,可是retransform有不能新增方法的限制。jdk的文档描述以下orm
The retransformation must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.rem
asmapi操做比较麻烦。可是能够直接修改方法体的内容。 转化前:
public void hello(){ int a=0; }
转化后:
public void hello(){ xxx int a=0; xxx }
asm的作法也有两种方式,一种是增长方法调用,而后把传递的值保存在threadlocal里,另一种就是把全部的内容写到方法里中。这两种均可以知足需求,第一种实现方式还简单一些,不用新增本地变量。
修改字节码的代码比较枯燥,全部直接附上代码地址,这次使用的是asm增长方法局部变量的方式作的,这样的demo网上博客没有,asm的手册中也没有这样的例子,若是有兴趣的能够去看看 https://github.com/xpbob/lightTrace