java线上排查神器:btrace使用示例
问题背景
最近我的一个正在生产环境运行的程序出现了故障,问题简单描述一下就是:这个程序需要实现任务调度,程序设置有最大运行数量的限制,如果一个任务失败了,那么这个任务在之后就会被重新调度,但是实际情况是这个失败了的任务并没有被重新调度,而是卡死了。
在阅读代码之后,发现需要打印程序中一个map类型的类属性的内容来定位最终的问题所在。但是,这种bug只发生在负载较大的时候,所以非常难复现。如果把程序停止,然后修改代码,运行新的程序,再想要复现这个bug就很困难了。
在查阅资料后,我发现了btrace这个工具可以完美解决我的需求。
BTrace简介
这个工具的官方Github仓库链接为:https://github.com/btraceio/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").
简单而言,这个工具可以把一段代码动态的插入到一个正在运行的Java程序里,而无需停止这个程序。其思想有点类似于动态插桩。关于BTrace的具体原理后面我会写一篇文章来解析一下。
但是,插入的代码是会受到一定的限制的,其中对本次编程影响最大的就是:方法调用只能有对BTraceUtils里面的方法的调用,如果有对其他方法的调用,就会报如下所示的错误:

使用BTrace
BTrace的具体使用这里就不赘述了,网上有很多博客介绍了这个工具的基本使用方法。(需要注意的是,网上很多文章代码里面引用的包已经过时了,如果遇到引用包错误的问题,建议看看btrace给的samples里面的代码,可以在这个里面的代码的基础上做自己的开发)
以下主要介绍一下怎样编写BTrace脚本来打印程序中的类属性。主要的思想是使用反射机制,BTrace脚本被注入之后,就和程序在同一个进程空间里了,那么就可以通过反射机制来获取到目标类的Class,然后获取到Field,最后通过对象来获取到这个类属性的值。具体的实现代码如下:
import org.openjdk.btrace.core.annotations.BTrace;
import org.openjdk.btrace.core.annotations.Injected;
import org.openjdk.btrace.core.annotations.OnMethod;
import org.openjdk.btrace.core.annotations.ProbeClassName;
import org.openjdk.btrace.core.annotations.ProbeMethodName;
import org.openjdk.btrace.core.annotations.Self;
import org.openjdk.btrace.core.annotations.ServiceType;
import org.openjdk.btrace.services.impl.Printer;
import org.openjdk.btrace.core.BTraceUtils;
import java.lang.reflect.Field;
import java.util.Map;
/**
* This script traces method entry into every method of
* every class in javax.swing package! Think before using
* this script -- this will slow down your app significantly!!
*/
@BTrace
public class WatchMapTrace {
@OnMethod(
clazz = "com.server.download.SubTaskDistributeCenter",
method = "autoDistribute"
)
public static void m(@Self Object o, @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
Class c=BTraceUtils.classForName("com.qzero.server.download.SubTaskDistributeCenter",BTraceUtils.contextClassLoader());
Field f=BTraceUtils.field(c,"threadMap",true);
Map map=(Map)BTraceUtils.get(f,o);
BTraceUtils.print(map+"");
// Get the element of map
Thread thread=(Thread)BTraceUtils.get(map,109579);
BTraceUtils.print("Thread status : "+BTraceUtils.threadState(thread));
}
}
代码是基于samples里面的AllMethods.java改的,其中的OnMethod注解指定了需要被插桩的方法,Self注解可以获取到含有这个方法的对象。
这里比较麻烦的点就是,btrace不允许除BTraceUtils以外的方法调用,不过好在BTraceUtils里面也给出了很多常用的方法,例如反射相关的,还有操作Map相关的,具体可以查看BTraceUtils.java的源码,链接如下:https://github.com/btraceio/btrace/blob/develop/btrace-core/src/main/java/org/openjdk/btrace/core/BTraceUtils.java
把这段脚本使用BTrace加载到正在运行的程序上,等到autoDistribute再次被调用时,程序里就会打印threadMap里面的内容了,我也是由此定位到了问题所在。
java线上排查神器:btrace使用示例的更多相关文章
- Java线上问题排查神器Arthas快速上手与原理浅谈
前言 当你兴冲冲地开始运行自己的Java项目时,你是否遇到过如下问题: 程序在稳定运行了,可是实现的功能点了没反应. 为了修复Bug而上线的新版本,上线后发现Bug依然在,却想不通哪里有问题? 想到可 ...
- Java线上问题排查思路及Linux常用问题分析命令学习
前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...
- Arthas - Java 线上问题定位处理的终极利器
前言 在使用 Arthas 之前,当遇到 Java 线上问题时,如 CPU 飙升.负载突高.内存溢出等问题,你需要查命令,查网络,然后 jps.jstack.jmap.jhat.jstat.hprof ...
- linux实用指令 | 程序员线上排查必知必会linux指令(持续更新中)
Linux线上排查程序员实用指南 一.乱码问题 二.帮助指令 1. help命令 2. man命令 3. info命令 三.性能监测与优化 1. top命令 参考资源 Linux线上排查程序员实用指南 ...
- 【转】java线上程序排错经验2 - 线程堆栈分析
前言 在线上的程序中,我们可能经常会碰到程序卡死或者执行很慢的情况,这时候我们希望知道是代码哪里的问题,我们或许迫切希望得到代码运行到哪里了,是哪一步很慢,是否是进入了死循环,或者是否哪一段代码有问题 ...
- 线上排查:内存异常使用导致full gc频繁
线上排查:内存异常使用导致full gc频繁 问题系统 日常巡检发现,应用线上出现频繁full gc 现象 应用线上出现频繁full gc 排查过程 分析dump 拉dump文件:小插曲:dump时如 ...
- BTrace : Java 线上问题排查神器
BTrace 是什么 BTrace 是检查和解决线上的问题的杀器,BTrace 可以通过编写脚本的方式,获取程序执行过程中的一切信息,并且,注意了,不用重启服务,是的,不用重启服务.写好脚本,直接用命 ...
- Java线上问题排查神器Arthas实战分析
概述 背景 是不是在实际开发工作当中经常碰到自己写的代码在开发.测试环境行云流水稳得一笔,可一到线上就经常不是缺这个就是少那个反正就是一顿报错抽风似的,线上调试代码又很麻烦,让人头疼得抓狂:而且deb ...
- JAVA线上常见问题排查手段(小结)
在平时开发过程中,对于线上问题的排查以及系统的优化,免不了和Linux进行打交道.每逢大促和双十一,对系统的各种压测性能测试,优化都是非常大的一次考验.抽空整理了一下自己在线上问题排查以及系统优化的一 ...
- Java线上应用故障排查之二:高内存占用
搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMemoryError: PermGen space 2.java.lang.OutOfMemoryError: Java ...
随机推荐
- JQuery元素滚动定位及获取元素的scrollTop,clientHeight,scrollHeight
scrollHeight为滚动DIV的实际总体高度,获取方式为:$(obj)[0].scrollHeight clientHeight为滚动DIV的可见高度,获取方式为:$(obj)[0].clien ...
- AI赋能金融风控:基于机器学习的智能欺诈检测系统实战教程
引言 在数字化转型浪潮中,金融欺诈手段呈现智能化.隐蔽化趋势.传统规则引擎已难以应对复杂多变的欺诈模式,而机器学习技术通过自动学习数据特征,正在重塑金融风控体系.本文将基于Python生态,以信用卡欺 ...
- 1. LangChain4j 初识,想使用Java开发AI应用?
1. 简介 LangChain4j 是一个基于 Java 的开源框架,用于开发 人工智能驱动的应用程序,尤其是涉及 大语言模型(LLM)交互 的场景.它的设计目标是简化开发者与大语言模型的集成过程,提 ...
- PHP桶排序:优化大数据集的高效算法解析与实践
本文由 ChatMoney团队出品 本文将介绍一种在 PHP 中实现的高效排序算法--桶排序.通过使用桶排序,可以快速地对大数据集进行排序,特别是在数据分布均匀的情况下.文章将简要介绍桶排序的原理,并 ...
- Spring中的一些注解
@SuppressWarnings("all") 隐藏一些无意义的报错提示 ** @ConfigurationProperties(prefix = "spring.da ...
- 你应该懂的AI大模型(十)之 LLamaFactory 之 LoRA微调Llama3
本文标题中说的微调 Llama3指的是局部微调,使用 LLamaFactory 局部微调 LIama3. 一.什么是LLamaFactory LLaMA-Factory 是一个开源的大型语言模型微调框 ...
- MKL普通矩阵运算示例及函数封装
本示例将介绍MKL中的矩阵乘法和求逆,使用MKL进行此类大型矩阵运算可大量节省计算时间和空间,但由于MKL中的原生API接口繁杂,因此将常用函数封装,便于后续使用,最后在实际例子中调用接口执行想要的矩 ...
- Luogu P9588 队列 题解
P9588 队列 考虑转化问题,将原问题转化为一个长度为 \(q\) 的序列.序列中 \(x\) 表示一段 \(1\sim x\) 的区间. 操作 \(1\) 每次增加时,输入 \(x\),在数组末尾 ...
- C语言中如何不用strcat函数来连接2个数组
C语言中如何不用strcat函数来连接2个数组? 今天就遇到这个问题,所以就尝试了一下,虽然这个问题被好多大佬看作就不是问题,但我还是对这方面做个简单的介绍. 下面是我的代码和运行情况. 其实简单的引 ...
- spring 中 mapper 中 resultMap resultType
简介 一般 resultMap 适用于自定义类型 resultType 适用于java自带的类型