Arthas - Java诊断利器
项目标题与描述
Arthas
是Alibaba开源的Java诊断工具,深受开发者喜爱。它允许开发者在生产环境中对Java应用进行问题诊断,而无需修改代码或重启服务器。Arthas支持JDK 6+,兼容Linux/Mac/Windows平台,采用命令行交互模式,提供丰富的Tab
自动补全功能,极大提升了问题定位和诊断的效率。
功能特性
- 类加载查看:查看类从哪个jar包加载,解决类冲突问题
- 方法监控:监控方法调用参数、返回值和异常
- 性能分析:生成火焰图,快速定位热点方法
- 动态追踪:无需重启即可追踪方法调用链路
- 在线诊断:直接在生产环境调试,无需线下重现
- JVM监控:实时查看JVM运行状态和系统属性
- 字节码增强:动态修改类字节码进行问题修复
- 多会话支持:支持多人同时诊断同一应用
安装指南
快速安装
使用以下命令一键安装Arthas:
curl -L https://arthas.aliyun.com/install.sh | sh
手动安装
- 下载最新版Arthas:
curl -O https://arthas.aliyun.com/arthas-boot.jar
- 启动Arthas:
java -jar arthas-boot.jar
系统要求
- JDK 6或更高版本
- Linux/Mac/Windows操作系统
- 至少100MB磁盘空间
使用说明
基础使用
- 启动Arthas并附加到目标Java进程:
java -jar arthas-boot.jar
- 查看帮助信息:
help
- 监控方法执行:
watch com.example.Class method "{params,returnObj}" -x 2
常用命令示例
- 查看JVM信息:
jvm
- 反编译类:
jad java.lang.String
- 监控方法调用:
trace com.example.Service * '#cost>100'
- 生成火焰图:
profiler start
profiler stop
核心代码
类加载器实现
public class ArthasClassloader extends URLClassLoader {
public ArthasClassloader(URL[] urls) {
super(urls, ClassLoader.getSystemClassLoader().getParent());
}
@Override
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
final Class<?> loadedClass = findLoadedClass(name);
if (loadedClass != null) {
return loadedClass;
}
// 优先从parent(SystemClassLoader)里加载系统类
if (name != null && (name.startsWith("sun.") || name.startsWith("java.")) {
return super.loadClass(name, resolve);
}
try {
Class<?> aClass = findClass(name);
if (resolve) {
resolveClass(aClass);
}
return aClass;
} catch (Exception e) {
// ignore
}
return super.loadClass(name, resolve);
}
}
方法监控实现
public abstract class AbstractTraceAdviceListener extends AdviceListenerAdapter {
protected final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();
@Override
public void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args) {
threadLocalWatch.start();
}
@Override
public void afterReturning(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args,
Object returnObject) {
double cost = threadLocalWatch.costInMillis();
// 处理监控结果
}
}
JVM信息获取
public class JvmCommand extends AnnotatedCommand {
private final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
private final ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
private void addRuntimeInfo(JvmModel jvmModel) {
Map<String, String> runtimeInfo = new LinkedHashMap<String, String>();
runtimeInfo.put("MACHINE-NAME", runtimeMXBean.getName());
runtimeInfo.put("JVM-START-TIME", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date(runtimeMXBean.getStartTime())));
jvmModel.setRuntimeInfo(runtimeInfo);
}
}
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码