四、Java探针技术
对于agent,是在vm启动,执⾏⽅法前,将字节码修改的服务代理。
对于javassist,是修改字节码具体实现。
最近⾯试阿⾥,⾯试官先是问我类加载的流程,然后问了个问题,能否在加载类的时候,对字节码进⾏修改
我懵逼了,答⽈不知道,⾯试官说可以的,使⽤Java探针技术,能够实现
我查了⼀下关于探针技术的知识:
基于javaAgent和Java字节码注⼊技术的java探针⼯具技术原理
图0-0:动态代理功能实现说明
我们利⽤javaAgent和ASM字节码技术开发java探针⼯具,实现原理如下:
jdk1.5以后引⼊了javaAgent技术,javaAgent是运⾏⽅法之前的。我们利⽤javaAgent和ASM字节码技术,在JVM加载class⼆进制⽂件的时候,利⽤ASM动态的修改加载的class⽂件,在监控的⽅法前后添加计时器功能,⽤于计算监控⽅法耗时,同时将⽅法耗时及内部调⽤情况放⼊处理器,处理器利⽤栈先进后出的特点对⽅法调⽤先后顺序做处理,当⼀个请求处理结束后,将耗时⽅法轨迹和⼊参map输出到⽂件中,然后根据map中相应参数或耗时⽅法轨迹中的关键代码区分出我们要抓取的耗时业务。最后将相应耗时轨迹⽂件取下来,转化为xml格式并进⾏解析,通过浏览器将代码分层结构展⽰出来,⽅便耗时分析,如图0-1所⽰。
图0-1:java探针⼯具原理图
Java探针⼯具功能点:
1、⽀持⽅法执⾏耗时范围抓取设置,根据耗时范围抓取系统运⾏时出现在设置耗时范围的代码运⾏轨迹。
2、⽀持抓取特定的代码配置,⽅便对配置的特定⽅法进⾏抓取,过滤出关系的代码执⾏耗时情况。
3、⽀持APP层⼊⼝⽅法过滤,配置⼊⼝运⾏前的⽅法进⾏监控,相当于监控特有的⽅法耗时,进⾏⽅法专题分析。
4、⽀持⼊⼝⽅法参数输出功能,⽅便跟踪耗时⾼的时候对应的⼊参数。
5、提供WEB页⾯展⽰接⼝耗时展⽰、代码调⽤关系图展⽰、⽅法耗时百分⽐展⽰、可疑⽅法凸显功能。
下⾯看个例⼦:
第⼀篇:
JavaAgent 是JDK 1.5 以后引⼊的,也可以叫做Java代理。
JavaAgent 是运⾏在 main⽅法之前的,它内定的⽅法名叫 premain ,也就是说先执⾏ premain ⽅法然后再执⾏ main ⽅法。那么如何实现⼀个 JavaAgent 呢?很简单,只需要增加 premain ⽅法即可。
看下⾯的代码和代码中的注释说明:
先写⼀个premain⽅法:
package agent;import java.lang.instrument.Instrumentation;publicclass pre_MyProgram {
/** * 该⽅法在main⽅法之前运⾏,与main⽅法运⾏在同⼀个JVM中
* 并被同⼀个System ClassLoader装载
* 被统⼀的安全策略(security policy)和上下⽂(context)管理
*
* @param agentOps
* @param inst
* @author SHANHY
* @create 2016年3⽉30⽇
*/publicstaticvoid premain(String agentOps,Instrumentation inst){
System.out.println("====premain ⽅法执⾏");java replace方法
System.out.println(agentOps);
}
/** * 如果不存在 premain(String agentOps, Instrumentation inst)
* 则会执⾏ premain(String agentOps)
*
* @param agentOps
* @author SHANHY
* @create 2016年3⽉30⽇
*/publicstaticvoid premain(String agentOps){
System.out.println("====premain⽅法执⾏2====");
System.out.println(agentOps);
}
publicstaticvoid main(String[] args) {
// TODO Auto-generated method stub
}
}
写完这个类后,我们还需要做⼀步配置⼯作。
在 src ⽬录下添加 META-INF/MANIFEST.MF ⽂件,内容按如下定义:
Manifest-Version: 1.0
Premain-Class: agent.pre_MyProgram
Can-Redefine-Classes: true
要特别注意,⼀共是四⾏,第四⾏是空⾏,还有就是冒号后⾯的⼀个空格,如下截图:
然后我们打包代码为 pre_MyProgram.jar
注意打包的时候选择我们⾃⼰定义的 MANIFEST.MF ,这是导出步骤:(1)
(2) 注意选择pre的MF⽂件
接着我们在创建⼀个带有main⽅法的主程序⼯程,截图如下:
这时候别忘了:
main函数也有MF⽂件:别写错了,不然导出报错:No main manifest attribute(说明MF⽂件写错了) Manifest-Version: 1.0Main-Class: alibaba.MyProgram
按同样的⽅法导出main的jar包命名为:MyProgram.jar
如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论