跳到主要内容

第三方诊断工具与实战

除了JDK自带的工具外,还有许多优秀的第三方诊断工具可以帮助我们更高效地排查和解决Java应用问题。本文将介绍Arthas、JProfiler等工具的使用方法,以及完整的故障排查实战流程。

Arthas: 阿里巴巴开源诊断利器

Arthas是阿里巴巴开源的功能强大的在线诊断工具,无需修改代码即可排查问题。

Arthas核心功能

快速启动

# 下载arthas启动脚本
$ curl -O https://arthas.aliyun.com/arthas-boot.jar

# 启动并选择进程
$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.7.1
[INFO] Found existing java process, please choose one and input the serial number.
* [1]: 8234 com.example.order.OrderServiceApplication
[2]: 9156 com.example.product.ProductServiceApplication
1

# 连接成功后进入交互界面
[arthas@8234]$

常用命令详解

dashboard - 实时监控面板

[arthas@8234]$ dashboard

ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPT DAEMON
1 main main 5 WAITING 0.0 0.000 0:0.031 false false
2 Reference Handler system 10 WAITING 0.0 0.000 0:0.000 false true
3 Finalizer system 8 WAITING 0.0 0.000 0:0.000 false true

Memory used total max usage GC
heap 128M 256M 1024M 12.50%
eden_space 64M 128M 256M 25.00% gc.ps_scavenge.count 45
survivor_space 8M 16M 32M 25.00% gc.ps_scavenge.time(ms) 342
old_gen 56M 112M 736M 7.61% gc.ps_marksweep.count 2
nonheap 48M 50M -1 96.00% gc.ps_marksweep.time(ms) 158

thread - 线程分析

# 查看最繁忙的5个线程
[arthas@8234]$ thread -n 5
"http-nio-8080-exec-1" Id=15 RUNNABLE (in native)
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
...

# 查看指定线程的堆栈
[arthas@8234]$ thread 15
"http-nio-8080-exec-1" Id=15 RUNNABLE
at com.example.order.OrderService.processOrder(OrderService.java:45)
...

# 查看阻塞其他线程的线程
[arthas@8234]$ thread -b
No most blocking thread found!

# 查看死锁
[arthas@8234]$ thread --state BLOCKED

jad - 反编译

# 反编译类
[arthas@8234]$ jad com.example.order.OrderService

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@1dde4cb2

Location:
/app/order-service.jar

/*
* Decompiled with Arthas
*/
package com.example.order;

public class OrderService {
public Order processOrder(OrderRequest request) {
// 反编译后的代码...
}
}

watch - 方法监控

# 观察方法的入参和返回值
[arthas@8234]$ watch com.example.order.OrderService createOrder "{params, returnObj}" -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms
ts=2024-11-27 10:15:23; result=@ArrayList[
@Object[][
@OrderRequest[id=12345, amount=199.00],
],
@Order[id=67890, status=CREATED],
]

# 只观察抛出异常的调用
[arthas@8234]$ watch com.example.order.OrderService createOrder "{params, throwExp}" -e

# 观察方法执行前后对象变化
[arthas@8234]$ watch com.example.order.OrderService createOrder "{params[0], target.cache.size()}" -b -s

trace - 调用链路追踪

# 追踪方法调用路径和耗时
[arthas@8234]$ trace com.example.order.OrderService createOrder
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 45 ms
`---ts=2024-11-27 10:20:15;thread_name=http-nio-8080-exec-1;id=15;is_daemon=true;priority=5;
`---[156.789ms] com.example.order.OrderService:createOrder()
+---[0.123ms] com.example.order.OrderValidator:validate()
+---[45.678ms] com.example.order.OrderRepository:save() #slow
+---[100.234ms] com.example.payment.PaymentClient:charge() #slow
`---[10.456ms] com.example.notification.NotificationService:notify()

# 只显示耗时超过100ms的调用
[arthas@8234]$ trace com.example.order.OrderService createOrder '#cost > 100'

monitor - 方法统计

# 统计方法调用次数和耗时(每5秒统计一次)
[arthas@8234]$ monitor -c 5 com.example.order.OrderService createOrder
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms
timestamp class method total success fail avg-rt(ms) fail-rate
-----------------------------------------------------------------------------------------------------------------------------
2024-11-27 10:25:00 com.example.order.OrderService createOrder 150 148 2 45.23 1.33%
2024-11-27 10:25:05 com.example.order.OrderService createOrder 163 160 3 52.18 1.84%

tt - 时光隧道

# 记录方法调用
[arthas@8234]$ tt -t com.example.order.OrderService createOrder
Press Q or Ctrl+C to abort.
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-----------------------------------------------------------------------------------------------------------------------------
1000 2024-11-27 10:30:01 45.123 true false 0x1a2b3c4d OrderService createOrder
1001 2024-11-27 10:30:02 52.456 true false 0x1a2b3c4d OrderService createOrder
1002 2024-11-27 10:30:03 0.000 false true 0x1a2b3c4d OrderService createOrder

# 查看某次调用的详细信息
[arthas@8234]$ tt -i 1002
INDEX 1002
GMT-CREATE 2024-11-27 10:30:03
COST(ms) 0.000
IS-RETURN false
IS-EXCEPTION true
THROW-EXCEPTION java.lang.NullPointerException
OBJECT 0x1a2b3c4d
CLASS com.example.order.OrderService
METHOD createOrder

# 重放某次调用
[arthas@8234]$ tt -i 1000 -p

Arthas命令速查表

命令功能常用参数
dashboard实时面板-i 刷新间隔
thread线程分析-n 显示前n个, -b 阻塞分析
jad反编译--source-only 只显示源码
watch方法监控-x 展开层级, -e 只看异常
trace调用追踪--skipJDKMethod 跳过JDK方法
monitor方法统计-c 统计周期
tt时光隧道-t 记录, -i 查看, -p 重放
sc搜索类-d 显示详情
sm搜索方法-d 显示详情
heapdump生成dump--live 只导出存活对象
profiler火焰图start/stop/getSamples

JProfiler: 商业级性能分析工具

JProfiler是功能强大的商业JVM分析工具,提供直观的可视化界面和丰富的分析功能。

核心特性

JProfiler主要功能

1. CPU分析

  • 采样分析: 低开销定位热点方法
  • 调用树: 展示方法调用关系
  • 热点方法: 按CPU时间排序的方法列表
  • 火焰图: 直观展示CPU时间分布

2. 内存分析

  • 对象分配热点: 哪些代码创建了最多对象
  • 内存增长趋势: 实时监控各类对象增长
  • 泄漏检测: 自动识别潜在内存泄漏

3. 线程分析

  • 线程状态历史: 可视化线程状态变化
  • 锁竞争分析: 找出锁等待热点
  • 死锁检测: 自动检测死锁

4. 数据库分析

  • JDBC调用统计
  • 慢SQL分析
  • 连接池监控

故障排查实战流程