Java七武器系列孔雀翎-- 问题诊断神器BTrace

古龙的小说对于大部分来说都不陌生,其中七武器系列中各个神器的名称更是在许多场合中被借用。

本次打算写一系列Java应用的分析诊断工具,也来借用下古龙的这些神器,来说明这些工作中使用起来事半功倍的分析诊断神器。

做为第一篇,先来介绍一个广泛应用于线上和线下的神器 BTrace。就像古龙在介绍「孔雀翎」时写道:

据说,「孔雀翎」发动之时,暗器四射,有如孔雀开屏,辉煌灿烂,而就在敌人目眩神迷之际,便已魂飞魄散。众多高手围攻山庄,结果全部丧生在「孔雀翎」下,从此,「孔雀翎」名扬天下。

而 BTrace 的厉害之处,在于其对于线上应用,也可以在不停止应用的情况下,直接通过 Trace 脚本执行分析探针指定的位置,了解问题。

BTrace是什么

BTrace is a safe, dynamic tracing tool for the Java platform. BTrace can be used to dynamically trace a running Java program (similar to DTrace for OpenSolaris applications and OS). BTrace dynamically instruments the classes of the target application to inject tracing code (“bytecode tracing”). Tracing code is expressed in Java programming language. There is also integration with DTrace for the OpenSolaris platform. admins were sundararajana and Jaroslov Bachorik

概括起来 BTrace 是一个动态的问题分析和诊断工具,类似于Solaris上的DTrace,基于JDK 提供的 Instrument特性,在JVM 运行过程中进行类的 retransform ,从而使定义的Trace script 生效。

比如分析如下的系统问题:

  • 应用中有大量的Socket连接,导致运行过程中会产生Socket句柄占用过多,系统异常。可以直接分析应用代码中打开和关闭Socket的地方,统计次数。类似可以应用于数据库连接等。

  • 应用的GC日志显示有频繁的 System.gc()的调用。可以直接分析调用方,打印调用Stack。

  • 线上应用统计某个方法的调用时间

  • 线上应用查看方法调用的返回值

更多可以参考UserGuide,或者参考下载包中包含的sample

基本原理

在BTrace中有探针(Probe)的一个概念,所有定义的OnMethod都可以看成一个探针,和现在APM工具里的概念类似,在特定的节点进行触发。临时新增的Trace 脚本,通过JVM TI 提供和Instrument动态增加到目标class中。相当于新增了一个trace方法,然后在源方法中进行trace方法的调用。

我们前面的文章曾经写过关于 class 的 HotSwap 实现,当时里面的几个图都是分析的 BTrace 对于目标 class 增加了探针之后的具体表现形式。(类加载器与类的热替换(Hotswap)

而整体的 Instrument 也是通过 JVMTI来实现类的 Retransform,这个在前面分析Debug的实现原理时也曾写过:当我们谈Debug时,我们在谈什么(Debug实现原理)

使用

具体到BTrace的使用,其实非常容易,我们介绍常用的两种方式:

1. 下载  https://github.com/btraceio/btrace/releases,在这里下载,然后编写 Trace 脚本,在命令行中执行 btrace PID script.java 即可。

2. 直接在 JvisualVM 中添加 BTrace 插件, 然后分析对应的应用时,直接右击进程,选择 Trace application,即可打开一个类似于 IDE 的窗口,在其中编写 Trace 脚本,执行 start即可。

Trace 脚本的编写也比较容易,在任意的方法中通过 OnMethod 声明探针,BTrace 中称之为 Probe,然后指定要 trace 的class 名称 和方法名称, 在方法体中直接编写对应的Probe被触发时要执行的逻辑。  更详细的内容可以参考下 UserGuide 或者附带的几个 sample。

比较而言,第二种使用更方便,但缺点是不支持远程 Trace。

例子

比如观察发现应用中有些时候会执行 System.gc()。 为了排查是否是在应用中直接调用,就可以通过 BTrace

对于数据库连接的获取等,可以直接判断其 getConnection 的调用

自己懒的写了,这几个是在gist 上找了几个截的图,方法了解其语法以及一些常用的用法。其中对于一些对象的构造方法调用等,可以直接指定方法为 <init>

甚至对于一个方法的执行时间,对于代码编写时没有添加Log时也不需要再增加,可以直接通过脚本进行,在方法退出时打印消耗时间:

此外,对于方法体内传入的参数,调用链的打印等都可以方便的进行。

也可以获取一个类的属性值,以及类内某个方法对于另外指定方法的调用。

而对于以上这些操作,最关键的是不需要停止应用,可以动态的进行修改,从而实现应用的分析诊断。

当然,对于执行完 Trace脚本后,这些内容会仍然保留在已加载的 class 内,直到应用重启或者 class 再次 transform。

PS: 上周末的几天没看后台,有不少留言。但由于超过了两天时间,微信公众号做的限制,不能直接发消息联系,已经没法回复。请再次留言,方便进行交流,谢谢。

链接:

UserGuide: https://kenai.com/projects/btrace/pages/UserGuide

觉得本文对你有帮助?请分享给更多人吧

关注『 Tomcat那些事儿  』 ,发现更多精彩文章!了解各种常见问题背后的原理与答案。深入源码,分析细节,内容原创,欢迎关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值