项目经验_之_性能分析
前言
Github:https://github.com/HealerJean
一、程序性能优化分析
1)分析什么
程序性能优化分析,主要是要找到一段程序中运行时间占用整体时间较长的代码,针对性的进行优化程序逻辑,最终缩短程序的运行时长。基本的核心思想就是在程序开始和结束处记录下开始时间、结束时间,这样就知道程序耗时情况
2)工具比较
| 工具名称 | 简介 | 优点 | 缺点 | 适用场景 | 选择建议 | 功能特点 | 定价策略 | 易用性 |
|---|---|---|---|---|---|---|---|---|
| JProfiler | 专业的 Java 性能分析工具,集成了 CPU、内存和线程分析等功能。 | 界面友好、支持多种数据视图、与主流 IDE 集成、分析结果准确。 |
商业软件,费用较高,对新手可能有一定学习曲线。 | 适用于需要深入分析应用性能的场景,如 CPU 和内存热点分析。 |
如果需要全面专业的性能分析工具,且预算充足,可选择。 | CPU 分析、内存泄漏检测、线程分析、SQL 性能检测等。 |
提供试用版,正式版需购买许可证。 | 界面直观,操作便捷,但高级功能需要学习。 |
| Async-profiler | 低开销的本地分析器,支持 CPU 和内存的火焰图分析。 |
低性能开销、精确、高效、支持火焰图、可用于生产环境。 | 命令行工具,缺乏 GUI 界面,使用需要一定技术基础。 |
在生产环境中进行低开销的性能分析,尤其适合高并发场景。 | 如果需要在生产环境进行性能采样,Async-profiler 是优秀选择。 |
``CPU 和内存采样、火焰图生成、支持多种 JVM。 |
免费开源。 | 需要命令行操作,学习曲线较陡。 |
二、火焰图介绍
1、什么是火焰图?
火焰图(Flame Graph)是一种用于性能分析(Profiling)的可视化工具,它以直观、交互式的方式展示程序的调用栈信息和资源消耗(如 CPU 时间、内存、I/O 等)。
它的名字来源于其独特的视觉样式:图形的底部是调用栈的根(如main函数),顶部是叶子函数,每一层代表调用栈的一个层级,函数按字母顺序从左到右排列,形似向上燃烧的火焰。
火焰图是性能分析的利器,它将复杂的调用栈数据转化为易于理解的视觉图形,极大地提高了定位性能问题的效率。掌握火焰图的阅读和生成方法,是现代软件开发者进行性能调优的必备技能之一。其核心思想——“将时间花在哪里”——是性能分析的根本出发点。
2、核心作用
- 定位性能瓶颈:快速识别消耗最多资源(通常是
CPU时间)的函数。 - 理解程序执行路径:清晰地看到函数之间的调用关系和调用栈深度。
- 分析热点代码:找出“热点”(
HotSpots),即被频繁执行或耗时较长的代码段。 - 优化代码性能:为代码优化提供数据支持,指导开发者优先优化最耗时的部分。
3、结构与解读
1)理解结构
火焰图就是看顶层的哪个函数占据的宽度最大。只要有”平顶”(
plateaus),就表示该函数可能存在性能问题。
-
x轴表示抽样数,如果一个函数在x轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。 -
y轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,底部是调用栈的起点(如main),向上是逐层的函数调用。一个函数框的高度代表它在调用栈中的层级。 -
函数框(
Frame):每个矩形块代表一个函数。- 块的 位置 表示其在调用栈中的位置。
- 宽度 = 资源消耗(如
CPU时间)的比例:一个函数框越宽,表示在采样期间,该函数(或其子函数)被调用时所占据的总资源越多。 - 颜色:通常使用暖色调(如红色、橙色)表示较高的
CPU活动,冷色调(如蓝色)表示较低的活动。但颜色本身没有严格标准,更多是为了视觉区分。
2)用例分析

a、调用链路
-
a()是最底层的函数(可能是入口点)。 -
a()调用了b()和h()(因为它们都在a()的正上方,且b()在左,h()在右)。 -
b()调用了c()。 -
c()调用了d()。 -
d()调用了f()和e()。 -
f()调用了g()。 -
i()是a()的另一个分支,与h()并列。
b、分析
- 首要目标是
g():它是最宽的函数,是最大的性能瓶颈。必须首先调查g()函数内部发生了什么。 - 次重要目标是
b()分支:a()调用b()的路径非常耗时,这导致了d()、f()等函数也显得很宽。需要深入调查b()分支的代码逻辑,特别是c()、d()、f()、g()的实现。 d()的宽度大,但根源在下方:不要只盯着d(),要向下追溯到f()和g()。b()和c()不是“没耗时”,而是“作为通道”:它们的宽度反映了它们调用的子函数的耗时。它们本身可能不耗时,但它们是耗时路径的一部分。a()的分支差异明显:b()分支远比h()分支耗时,这提示a()内部的条件逻辑可能导致了性能差异。
c、最终建议
- 优先调查
g():这是最明显的热点。 - 其次调查
b()分支的完整调用链:从b()到c()、d()、f()、g()。 - 分析
a()的代码:确认b()和h()分支的条件逻辑,看看是否可以优化b()分支的执行效率或减少其执行频率。 - 忽略
i()和h():除非你发现其他问题,否则它们不是当前的优化重点。
4、如何解读?
- 找最宽的块:位于顶部(叶子节点)的宽块通常是直接消耗资源的函数,是优化的首要目标。
- 看调用链:从一个宽块向下追踪,可以清晰地看到是哪个调用路径导致了该函数的频繁执行。
- 识别“平顶”
vs“尖顶”:- 平顶(如
malloc):表示该函数自身消耗资源,是性能瓶颈。 - 尖顶(如
main):表示该函数主要消耗在调用子函数上,瓶颈在其子函数中。
- 平顶(如
5、如何生成火焰图?
1)数据采集:
- 使用性能分析工具采集调用栈数据。
- 常用工具:
Linux:perf(perf record)Java:async-profiler,jstack,JFR- 通用:
eBPF/bpftrace
1、启动 profiler
$ profiler start
Started [cpu] profilin
2、获取已采集的 sample 的数量
$ profiler getSamples
23
3、查看 profiling 状态:可以查看当前 profiler 在采样哪种event和采样时间。
$ profiler status
[cpu] profiling is running for 4 seconds
4、停止 profiler:生成火焰图格式结果
默认情况下,结果是 Flame Graph 格式的 html 文件,也可以用 -o 或 --format 参数指定其他内容格式,包括 flat、traces、collapsed、flamegraph、tree、jfr。
$ profiler stop --format flamegraph
profiler output file: /tmp/test/arthas-output/20211207-111550.html
OK
在--file参数指定的文件名后缀为 html 或 jfr 时,文件格式可以被推断出来。比如--file /tmp/result.html 将自动生成火焰图。
5、通过浏览器查看 arthas-output 下面的 profiler 结果
默认情况下,arthas 使用 3658 端口,则可以打开: http://localhost:3658/arthas-output/ 查看到arthas-output目录下面的 profiler 结果:

2)数据处理:
- 将原始的调用栈数据(通常是堆栈跟踪列表)转换成火焰图工具能识别的格式(通常是折叠栈格式:
func1;func2;func3 10,表示调用栈func1->func2->func3出现了10次)。 - 这一步可能需要编写脚本或使用工具(如
stackcollapse-perf.plforperfdata)。
3)生成可视化:
- 使用
FlameGraph开源工具(由BrendanGregg开发)的flamegraph.pl脚本,将折叠栈数据转换为SVG格式的火焰图。 - 命令示例:
flamegraph.pl collapsed_stacks.txt > output.svg - 生成的
SVG文件可在浏览器中打开,支持鼠标悬停查看详情、点击缩放等交互操作
6、优缺点
1)优点
- 直观清晰:一目了然地看到性能瓶颈。
- 信息丰富:同时展示调用关系和资源消耗。
- 交互性强:可缩放、搜索、高亮。
- 跨平台:原理通用,可用于多种语言和系统。
2)缺点
- 基于采样:是统计结果,可能存在误差,不一定捕获到瞬时峰值。
- 无法显示代码逻辑:只显示“谁在运行”,不显示“为什么这样运行”。
- 需要符号信息:要获得有意义的函数名,程序需要编译时包含调试符号(如
-g)。 - 对短生命周期程序不敏感:如果程序运行时间很短,可能采样不到足够的数据。
三、Java Flight Recorder
Java Flight Recorder是Java开发者和运维人员不可或缺的工具。它就像一个“黑匣子”,能够记录应用在运行时的详尽信息。结合Java Mission Control,可以快速定位性能瓶颈、分析GC问题、排查疑难杂症,极大地提升了Java应用的可观测性和可维护性。对于任何严肃的Java生产环境,掌握JFR的使用都是必备技能。
1、核心概念
1)概念
JDK飞行记录器 (JFR)是一种结构化日志记录工具, 它记录广泛的系统级(system-level)事件。JFR会持续记录JVM中的 一系列事件,用于诊断问题。这种方式的优势是,它会按时间顺序,捕获导致事故的,详细系统信息。JFR被设计的,对于性能影响很小,所以 可以安全地在生产环境长时间运行。对于运行系统的影响比较小,额外占用资源小于1%,但是随着开始的事件或者记录线程增多,性能开销也会随之增多
- 事件 (
Events):JFR的核心是事件。它会记录各种类型的事件,例如:JVM内部事件:GC活动、JIT编译、线程活动、类加载/卸载。- 应用程序事件: 方法执行(通过探针或注解)、锁竞争、
I/O操作、异常抛出。 - 系统事件:
CPU使用率、内存使用情况、网络活动。 - 自定义事件: 开发者可以定义自己的事件来记录特定的业务逻辑。
- 记录 (
Recording):JFR收集的数据被组织成一个“记录”文件(通常是.jfr文件)。这个文件包含了在特定时间段内发生的事件的二进制数据。 - 开销极低:
JFR的设计目标之一是生产环境可用,其默认配置下的性能开销通常低于2%,使其非常适合在生产系统中进行问题诊断。
3)主要功能
- 性能分析 (
Profiling):CPU分析: 精确地找出消耗CPU时间最多的方法(采样或基于事件)。- 内存分析: 分析对象分配热点,了解哪些代码创建了大量对象。
- 锁分析: 识别线程阻塞和锁竞争,帮助解决并发性能问题。
- 垃圾回收 (
GC) 分析:详细记录每次GC的类型、持续时间、回收的内存量、堆内存变化等,是调优 GC 性能的关键工具。 - 应用监控与故障排查:
- 当应用出现卡顿、高延迟或崩溃时,可以通过分析
JFR记录回溯问题发生时的系统状态。 - 记录异常堆栈信息。
- 当应用出现卡顿、高延迟或崩溃时,可以通过分析
- 容量规划与基准测试:通过长期记录,了解应用在不同负载下的资源消耗模式,为容量规划提供数据支持。
2、如何使用 JFR
1)JDK 版本
如果你使用的
JDK版本为JDK11及以上的版本,那么恭喜你~你将可以免费使用Java Flight Recorder
-
Oracle JDK8及以上版本:需通过添加-XX:+UnlockCommercialFeatures参数启用(仅限商业用途)。 -
•
OpenJDK 11及以上版本:免费开源版本,无需商业授权即可使用。
| 特性 | JDK 8 (Oracle JDK) | JDK 11+ (OpenJDK / Oracle JDK) |
|---|---|---|
UnlockCommercialFeatures |
必须添加,放最前面 | 已废弃,添加会报错 |
FlightRecorder |
需要手动开启 | 默认开启,可省略 |
| JFR 是否免费 | 商业特性(需授权) | 完全开源免费 |
dumponexit=true |
支持 | 支持 |
settings=profile |
支持 | 支持 |
2)JVM 参数
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=filename=/export/Logs/recording.jfr,dumponexit=true,settings=profile,delay=10s
| 参数 | 说明 | 备注 |
|---|---|---|
-XX:+UnlockCommercialFeatures |
解锁 JDK 中的商业特性 |
这个参数在 OpenJDK 8 中不存在, |
-XX:+FlightRecorder |
启用 Flight Recorder 功能 |
在 JDK 8 中需要显式开启。从 JDK 11+ 开始,JFR 默认是启用的 |
-XX:StartFlightRecording=... |
在JVM 启动时立即开始一个 Flight Recording |
以下是对应的参数解释 |
-XX:StartFlightRecording=...
duration: 记录时长(例如60s,5m)。filename: 输出文件名。settings: 使用预设的配置文件(如profile,default)。maxAge,maxSize: 循环记录时的限制。delay:系统启动 + 预热需要10分钟左右的时间,所以延迟监控- 如果你的应用启动很快,且主要关注稳定运行时的性能(如在线服务的日常监控),那么
delay=10m是一个合理的选择,可以过滤掉预热期的噪音。 - 如果你的应用启动较慢,或者你正在排查启动慢、初始化异常等问题,那么
delay=10m是不合适的,应该移除或缩短延迟时间(如delay=30s)
- 如果你的应用启动很快,且主要关注稳定运行时的性能(如在线服务的日常监控),那么
Settings 名称 |
用途 | 性能开销 | 适用场景 |
|---|---|---|---|
default |
标准事件(CPU、内存、GC、线程等) |
低 (~1%) | 通用分析 |
profile |
更详细的事件(方法采样、分配率等) | 中 (~2-5%) | 深度性能分析 |
lowoverhead |
仅关键事件(GC、异常等) |
极低 (<1%) | 生产环境长期监控 |
continuous |
环形缓冲区模式(不写入磁盘) | 低 | 生产环境诊断 |
3)问题
a、为啥开销比较低
JFR 的低开销不是偶然的,而是通过架构设计、底层实现和精细化控制共同实现的。正因如此,它成为目前最适合在生产环境中长期开启的 Java 性能诊断工具。
| 特性 | 如何降低开销 | 说明 |
|---|---|---|
| 事件驱动 | 只记录关键事件,不侵入业务逻辑 | JFR 不是持续记录所有方法调用或对象分配,而是只记录特定的、预定义的“事件” |
JVM 内建 |
使用 C++ 实现,避免 Java 层开销 |
JFR 是 JVM 内部原生实现的,而不是一个外部代理或 Java 库。 |
| 线程本地缓冲 | 减少锁竞争,异步提交 | JFR 为每个线程分配一个本地缓冲区(Thread-Local Buffer),事件先写入本地缓冲,而不是直接写入全局文件或共享结构。 |
| 可配置采样 | 按需开启,灵活控制粒度 | JFR 允许你精细控制哪些事件开启、采样频率多高,从而平衡开销与信息量。 |
| 高效二进制格式 | 节省存储和 I/O |
JFR 记录的数据是高度优化的二进制格式 |
| 生产级优化 | 经过多年大规模验证 |
三、Java Mission Control (JMC)
如果
Java Flight Recorder是 “黑匣子” 那么Java Mission Control就是打开 “黑匣子” 的的钥匙。
1、介绍
1)是什么?
Java Flight Recorder (JFR) 是 JVM 内置的低开销运行时数据记录引擎,负责采集性能数据并生成 .jfr 二进制文件;而 Java Mission Control (JMC) 是其官方配套的高级分析与可视化工具,能将这些难以直接解读的数据转化为直观的图形、表格和图表,帮助开发者进行性能分析、故障排查和 JVM 调优,现已发展为功能全面的 Java 应用性能管理“一站式平台”。
-
现代替代方案:
-
虽然
JMC是官方工具,但社区也有其他工具支持.jfr文件,如:
jfr命令行工具(JDK自带)Async-Profiler+Flame Graph
-
-
JMC的独立性:-
JMC可以独立安装,也可以集成在IDE中(如IntelliJ IDEA插件)。 -
它既能分析离线的
.jfr文件,也能连接运行中的JVM进行实时监控。
-
2)应用场景
-
性能调优:当你的
Java应用出现性能瓶颈时,JMC可以帮助你识别哪些代码段消耗了大量资源,从而指导优化工作。 -
故障排查:如果应用出现异常或者挂起,可以通过
JMC查看当时的线程堆栈、内存状态等信息,快速定位问题。 -
监控生产环境:在生产环境中,
JMC的飞行记录器可以持续收集数据,为运维团队提供宝贵的诊断信息。
3)特点与优势
-
轻量级:
JMC对应用性能的影响极小,即使是高负载环境也能胜任。 -
全面的数据采集:覆盖了从
JVM内部到应用层的各种运行指标,提供全方位的洞察。 -
易用性:直观的
GUI设计,使得即使是不熟悉命令行的开发者也能轻松上手。
4、安装
https://www.oracle.com/java/technologies/javase/jmc9-release-notes.html
启动测试代码后,启动
JMC就可以在左侧的JMV浏览器中看到当前机器所有的JVM进程,选择测试代码进行通过MBean服务器进行连接,然后可以看到概览界面。

2、整体布局
JMC 界面分为左右两大部分:
| 位置 | 说明 | 功能 |
|---|---|---|
| 左侧 | JVM 浏览器(JVM Browser) |
列出当前系统中所有可连接的 Java 进程(JVM) |
| 右侧 | 监控面板与分析视图 | 显示选中 JVM 的实时性能数据、内存、线程等信息 |
1)左侧:JVM 浏览器
-
功能:显示本机或远程运行的所有
Java虚拟机(JVM),您可以从中选择一个进行监控或分析。 -
问题 1: 为什么你没启动
Java应用,却能看到JVM- 打开了
IDEA,它本身就是一个Java应用。 - 它会启动多个
JVM实例:- 主程序:
com.intellij.idea.Main Maven/Gradle构建服务器:RemoteMavenServer36- 插件、代码分析、索引等子进程
- 主程序:
- 打开了
2)右侧:概览面板
a、仪表盘
| 位置 | 指标 | 含义 |
|---|---|---|
| 仪表盘 | Used Java Heap Memory |
当前 JVM 堆内存使用量(MB) |
JVM CPU Usage |
JVM 所占 CPU 使用率 |
|
Live Set + Fragmentation |
堆中“存活对象”占用空间比例 + 内存碎片化程度 |
b、处理器使用率图表
- 显示
JVMCPU使用率 和 机器整体CPU使用率 - 可见
JVM占用非常低( <5%),说明当前应用负载很轻

c、内存使用图表(Memory)
- 显示不同内存区域的变化趋势
- 关键项:
- Committed Java Heap:已提交给
JVM的堆内存 - Total Physical Memory:物理内存总量
- Used Java Heap Memory:堆内存实际使用量
- Used Physical Memory:系统总内存使用量
- Committed Java Heap:已提交给

d、下方标签页:深入分析功能
| 标签 | 功能 |
|---|---|
| 概览 | 当前页面,显示基础监控数据 |
| MBean 浏览器 | 查看 JVM 中暴露的 MBeans(管理接口),可用于自定义监控 |
| 触发器 | 设置事件触发条件(如内存超过阈值时报警) |
| 系统 | 查看操作系统信息、文件系统、网络等 |
| 内存 | 深入分析堆内存,支持堆转储(Heap Dump)分析 |
| 线程 | 查看线程状态、死锁、阻塞情况 |
| 诊断命令 | 执行 JMX 命令,如强制 GC、dump 堆栈等 |
3、实时分析
1)JMC 触发器
JMC触发器可以理解为一个JVM告警,可以对JVM进程的各种指标设置阈值,在超过指定阈值后可以收到告警提示,对进程异常情况监控十分方便。
/**
* 消耗CPU的线程 通过不断地进行浮点运算来提高对 CPU 的消耗。
*/
private static void cpuHigh() {
Thread thread = new Thread(() -> {
Thread.currentThread().setName("cpu_high_thread");
while (true){
double pi = 0;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
pi += Math.pow(-1, i) / (2 * i + 1);
}
System.out.println("Pi: " + pi * 4);
}
});
thread.start();
}
通过弹窗告警可以看到告警原因,以及对应的类信息,但是这里目前还看不到告警的具体原因,也就是说比如 CPU 占用率过高,并不知道为什么 CPU 会使用过高。

2)JMC 分析内存
/**
* 不断新增 BigDecimal 信息到 list,每秒10000个
*/
private static void allocate() {
new Thread(()->{
Thread.currentThread().setName("memory_allocate_thread");
List<BigDecimal> list = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
for (int i1 = 0; i1 < 10; i1++) {
list.add(new BigDecimal(i));
}
}
}).start();
}
通过内存页面可以看到堆内存分配情况,由于问题代码中再不断地分配 BigDecimal 对象,这里也可以看出 BigDecimal 对象占用了最多的内存。对分析内存过高情况有一定的帮助。

3)内存分配对应的线程
如果想进一步分析内存占用来源,可以到线程页面,通过勾选分配复选框,可以看到哪个线程占用的内存最多,还可以看到线程的具体的调用堆栈。

4)JMC 分析 CPU
线程页面勾选
CPU概要分析可以查看占用CPU最高的线程,这里线程cpu_high_thread在不断地进行浮点计算,占用了较多的CPU。

5)JMC 分析死锁
线程页面勾选死锁检测可以直接看到死锁线程信息,并且有具体的线程堆栈。

另外一种检查死锁的方式是直接打印线程信息,在线程信息的最后部分,会输出死锁线程信息。使用 JMC 可以通过诊断命令中的 Thread.print 命令来实现这个功能。

4、离线分析
1)获取 JRC 文件

2)自动分析
3)异常错误分析
双击自动分析结果中规则名称为:引发的异常错误 或 点击左边菜单栏Java应用程序-》异常错误,利用界面底部的火焰图信息,我们能够定位并分析相关异常错误的调用栈
四、Arthas
1、什么是 Arthas?
Arthas 是阿里开源的一款 Java 诊断工具,可以在不修改代码、不重启服务的情况下,对线上运行的 Java 应用进行实时诊断,例如:
- 查看方法调用栈、参数、返回值
- 动态追踪方法执行耗时(trace)
- 监控 JVM 状态(线程、内存、GC 等)
- 热更新代码(通过 redefine/retransform)
- 反编译已加载的 class
- 条件断点、监控特定方法调用等
通常使用方式是 attach 到目标 Java 进程,但需要手动操作或脚本支持。
2、SpringBoot 接入
1)arthas-spring-boot-starter
arthas:
enabled: true
tunnel-server: ws://127.0.0.1:7777/ws
agent-id: my-app-01
telnet-port: 3658
http-port: 8563
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spring-boot-starter</artifactId>
<version>最新版本(如 4.0.3)</version>
</dependency>
2)arthas-spring-boot-starter 的作用
这个 starter 的核心价值是:让 Arthas 在 Spring Boot 应用启动时自动嵌入并开启服务,无需手动 attach。
- 自动集成
Arthas Agent- 应用启动时自动加载
Arthas,并以内嵌模式(telnet 或 web console)运行。
- 应用启动时自动加载
- 提供 Web 控制台(可选)
- 默认开启
Web UI(如http://localhost:8563),可通过浏览器直接使用 Arthas。
- 默认开启
3)使用场景
Arthas本身不“吃”CPU,但用错了命令会“吃掉”你的应用CPU。
- 开发/测试环境:快速调试接口、查看方法执行逻辑。
- 生产环境(谨慎使用):紧急排查性能问题、死锁、异常调用链等。
- 容器化部署(如
Kubernetes):通过Web Console或Tunnel远程接入诊断。
| 使用方式 | CPU 开销 | 是否适合生产 |
|---|---|---|
仅 attach,不执行命令 |
极低(≈0) | 安全 |
执行 dashboard / jvm |
很低 | 安全 |
执行 thread -n 3(默认间隔) |
低~中(因 JDK 而异) | 谨慎使用 |
长时间 trace / watch 高频方法 |
高(可能雪崩) | 禁止 |
profiler start(火焰图) |
低(<2%) | 推荐 |
4)注意事项
- 安全风险:
Arthas拥有极高权限(可执行任意代码),切勿在公网暴露端口。 - 建议配合防火墙、认证或仅限内网访问。
- 生产环境建议通过
arthas.tunnel-server+ 白名单方式远程接入,而非直接开放 HTTP/Telnet 端口。
五、FAQ
1、Arthas 和 Java Flight Recorder
| 维度 | Arthas | Java Flight Recorder (JFR) |
|---|---|---|
| 开发方 | 阿里巴巴(开源) | Oracle |
| 是否需要重启/attach | 可 attach 到运行中进程,或通过 starter 嵌入 |
默认内置,无需额外工具,可启动时开启或动态启用 |
| 交互方式 | 交互式命令行/Web 控制台,实时执行命令(如 trace、watch、monitor) |
录制 + 离线分析,生成 .jfr 文件后用工具 |
| 实时性 | 强:可实时查看方法调用、参数、返回值、修改行为等 | 弱:需先录制一段时间,再分析历史数据 |
| 代码级调试能力 | 极强:支持反编译、动态 trace、条件监控、热更新字节码等 | 无:不能查看方法参数/返回值,不能干预程序执行 |
| 性能开销 | 中等(按需启用,命令触发时才有开销) | 极低(设计目标就是低开销持续录制) |
| 主要用途 | 线上问题快速排查、动态诊断、调试 | 性能剖析、长时间运行分析、JVM/系统级事件追踪 |
| 是否能修改程序行为 | 可以(如 redefine class) | 不能 |
| 是否开源免费 | 是(Apache 2.0) | OpenJDK 11+ 免费;Oracle JDK 8 需商业许可 |
1)你想看某个方法的入参和返回值?
Arthas:用watch com.example.Service method "{params, returnObj}"实时打印。JFR:做不到。JFR不记录具体业务方法的参数/返回值(除非你手动埋点 Event)。
2)你想分析 CPU 热点或 GC 行为?
JFR:原生支持,低开销录制 CPU、内存、线程、GC、I/O 等事件,可视化分析强大。Arthas:可通过thread、dashboard看基础指标,但深度不如 JFR。
3)你想在线上不停机的情况下调试?
Arthas:专为此设计,支持动态追踪、反编译、甚至临时修复(redefine)。JFR:只能“记录”,不能“干预”或“交互”。
4)你想做长期性能基线监控?
JFR:适合持续录制(如每小时一段),用于趋势分析。Arthas:不适合长期自动采集,更适合“按需诊断”。
5)使用场景
| 场景 | 推荐工具 |
|---|---|
| 线上突发问题排查(如接口慢、异常) | Arthas |
性能优化、CPU/内存瓶颈分析 |
JFR + JDK Mission Control |
| 需要看方法内部参数/返回值 | Arthas |
| 低开销、7x24 小时监控 JVM 行为 | JFR |
| 不能重启服务,但要调试代码逻辑 | Arthas |


