BTrace作为线上问题定位神器,它在侵入、安全、资源占用等方面表现的都非常出色。本文记录了作者平时工作中使用Btrace的场景,以供大家参考。
BTrace限制
关于BTrace的安装配置使用,网络上有太多的教程了,本文就不再重复造轮子了,但是还是非常有必要再次重申BTrace的限制。因为不正当的使用Btrace可能根本拿不到自己想要的结果,甚至导致JVM崩溃,建议脚本使用之前先经过验证,然后再使用到线上环境。
使用Btrace时,需要确保追踪的行动是只读的(即:追踪行动不能修改程序的状态)和有限的(即:追踪行动需要在有限的时间内终止),一个追踪行为需要满足如下的限制:
- 不能创建新的对象
- 不能创建新的数组
- 不能抛出异常
- 不能捕获异常
- 不能对实例和静态方法随意调用,只有com.sun.btrace.BTraceUtils中的public static方法或者当前脚本中申明的方法,可以被BTrace程序调用。
- (1.2之前)不能存在实例字段和方法。BTrace类只允许静态公共void返回方法,并且所有字段必须是静态的。
- 不能将目标程序中的类和对象中的静态或者实例字段指派给BTrace程序。但是,可以将BTrace类自己的静态字段(“trace state”是可以改变的)指派给自己。因为引用的传递可能导致目标程序别修改,而BTrace自身的跟踪字段只有BTrace自己在使用,所以不怕修改。
- 不能有外部,内部,嵌套或者本地的类。
- 不能有synchronized块和方法。
- 不能有循环(for,while,do…..while)。
- 不能继承抽象类(父类只能为java.lang.Object)。
- 不能实现接口。
- 不能有断言语句。
- 不能使用class保留字。
以上的限制可以通过通过unsafe模式绕过。追踪脚本和引擎都必须设置为unsafe模式。脚本需要使用注解为@BTrace(unsafe = true),需要修改BTrace安装目录下bin中btrace脚本将-Dcom.sun.btrace.unsafe=false改为-Dcom.sun.btrace.unsafe=true。
注:关于unsafe的使用,如果你的程序一旦被btrace追踪过,那么unsafe的设置会一直伴随该进程的整个生命周期。如果你修改了unsafe的设置,只有通过重启目标进程,才能获得想要的结果。所以该用法不是很好使用,如果你的应用不能随便重启,那么你在第一次使用btrace最终目标进程之前,先想好到底使用那种模式来启动引擎。
性能分析
大家经常会发现自己某一个服务变慢,但是由于这个服务背后由很多的业务逻辑或者方法块构成,这个时候就不好定位到底慢在哪个地方。Profiling就可以很好的解决该问题,我们只需要大概的定位问题可能存在的地方,通过包路径的模糊匹配,就可以很快找到问题所在。
1 |
|
当然如果你怀疑一个类的某一个方法,也可以采用精准定位的方式来进行追踪。
1 |
|
如果你只想定位执行时间超过某个阀值的函数,也可以使用@Duration来解决。
1 |
|
异常分析
有时候,开发人员对异常的处理不合理,导致某些重要异常别人为吃掉,并且没有任何日志或者日志不详细,导致问题定位困难,那么我们可以使用下面的Tracer来处理。
1 |
|
参数及返回结果
1 |
|
jdbc问题追踪
1 |
|
死锁排查
很多时候,我们怀疑程序是否有死锁,可以用下面的脚本扫描下,非常简单方便。
1 |
|
我只是将我工作中经常用到的一些列举出来了,还有很多没有列举,可以详见链接。
参考文章:
Btrace一些你不知道的事