⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/yingrou5033 「Cx晨星」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

一、前言:为什么要做性能分析?

无论你在写 Spring Boot、微服务、还是大型企业级后端,性能瓶颈都是无法绕过的挑战。

当我们遇到以下问题时,性能分析器(Profiler)就能大显身手:

  • 某接口响应慢,不知道是哪一段代码卡住了
  • CPU 占用率过高,线程频繁阻塞
  • 内存持续上涨,怀疑内存泄漏
  • 想弄清楚一个复杂调用链的耗时分布

IntelliJ IDEA自2023.2版本开始正式集成了强大的Profiler工具,为Java开发者提供了开箱即用的性能分析能力。

本文将以IntelliJ IDEA 2024.3.2.1 (Ultimate Edition)为例,详细介绍如何使用这款强大的工具来监控和分析Java后端应用的性能。

二、Profiler 简介与原理

Profiler 的核心作用是监控应用在运行时的资源消耗,尤其是:

  • CPU: 哪段代码占用了多少 CPU 时间
  • Memory: 哪些对象被频繁创建、未及时释放
  • Threads: 线程状态、死锁、上下文切换频率
  • GC: 垃圾回收的时间与频率

在 IDEA 中,Profiler 实际上使用了 Async Profiler 和 Java Flight Recorder (JFR) 两种技术结合:

  • Async Profiler: 采样型 CPU 分析器,性能损耗极低(1~2%)
  • JFR: 由 Oracle 提供的 JVM 内置事件记录器,支持更全面的性能事件追踪

三、启动方式

在启动类上,点击右键,选择【更多运行/调试】,选择【使用IntelliJ Profiler分析XXX.main()】。

以Spring boot项目为例,A接口响应慢,想看A接口代码的耗时情况,可通过下面步骤进行分析。

  • 选择【使用IntelliJ Profiler分析XXX.main()】启动该项目。
  • 调用A接口。
  • 在“使用IntelliJ Profiler分析”窗口或者“分析器”窗口点击【停止分析并显示结果】。
  • 在“分析器”窗口中查看“火焰图”、“调用树”等(具体见后面的功能详解)。

项目运行过程中,可在“分析器”窗口,右键选择此进程,点击【捕获内存快照】、【获取线程转储】、【CPU和内存实时图表】进一步分析(具体见后面的功能详解)。

三、Profiler核心功能详解

3.1 CPU性能分析

3.1.1 火焰图(Flame Graph)

火焰图是最直观的性能分析视图:

  • 横轴表示方法调用栈的展开;
  • 纵轴表示调用深度;
  • 每个方块的宽度代表 CPU 时间/总时间;
  • 最“宽”的那块通常就是你的瓶颈所在。

此视图可帮助你直观地查看选定线程的调用堆栈,并了解其随时间的变化情况。堆栈框架越宽,方法的执行时间越长。黄色块表示用户(自己写的)代码,灰色块表示库代码(Java标准类库或第三方依赖代码)。

“

小技巧:

  • 将鼠标悬停在某个方法上可查看CPU时间及占比。
  • 点击方块可向下钻取调用链。
  • 使用搜索框(Ctrl+F)快速定位特定方法。

3.1.2 调用树(Call Tree)

调用树是火焰图的层级结构版本,更适合分析复杂的业务逻辑调用:

  • 展示 调用关系 + 时间占比
  • 支持按 CPU 时间 或 总时间(包括等待时间) 排序

此视图显示方法使用的 CPU 时间百分比、应用程序中的方法执行路径以及样本总数。调用树有助于快速概览应用执行内容并检测关键执行路径,可以快速定位哪个方法耗时最多,哪个子调用拖慢了整体性能。

3.1.3 方法列表(Method List)

此视图显示了在分析数据时执行的方法列表。所有方法均按累计采样时间排序。每个选定的方法都有多个视图,可以显示该方法的调用方(反向跟踪)或被调用方,适合查找高频小方法或潜在热点。

3.1.4 时间线(Timeline)

这是线程活动随时间变化的可视化呈现,有助于检测异常的垃圾回收(GC)活动、多线程问题(如活锁)等,对分析“偶发卡顿”或“周期性波动”极有帮助。

活锁是一种特殊类型的线程阻塞问题。与死锁中线程完全被“卡住”、一动不动不同,处于活锁中的线程并没有停止运行,它们也在持续工作、改变状态,但整个系统却无法取得任何实质性的进展。

可以把它想象成两个非常礼貌的人在一条狭窄的走廊里相遇,都想让对方先过:

  • 线程A: 向左移动让路,但发现对方也向左了,于是又向右移动。
  • 线程B: 同样,向左移动让路,但发现对方也向左了,于是又向右移动。
  • 结果: 他们就这样在走廊里左右摇摆,不断地“工作”(移动),但始终无法通过对方,无法向前推进。

3.2 内存分析

3.2.1 捕获内存快照

在该视图中我们可以看到:

  • char[]、String、Object[] 等对象的数量与占用大小;
  • “浅层” 表示对象本身占用的内存;
  • “保留” 表示对象加上其引用链所占存;
  • 右侧 “GC 根 (GC Root)” 区域展示当前对象图的根节点,即 JVM 垃圾回收器无法回收的起点对象。当某对象无法被回收时,可以通过 “GC Roots 路径” 找出是谁在引用它。

“

适用场景:

  • 用于追踪内存泄漏的根因。
  • 当某对象无法被回收时,可以通过 “GC Roots 路径” 找出是谁在引用它。
  • 检查是否有错误的静态集合、单例、线程本地变量等持有强引用。

分析技巧:

  • 若路径中出现业务类(如 UserCache、TaskManager)则极可能为泄漏源。
  • 右侧”最大对象“区域列出了当前堆中占用内存最多的对象类型及其实例。它按对象的「保留大小(Retained Size)」进行排序,即对象本身 + 其引用链上的所有对象总占用量。

“

适用于:

  • 快速找出“内存大户”,如:byte[] 缓冲区、String 池、HashMap 缓存等;
  • 识别内存泄漏热点(例如某缓存未及时清理)。

分析技巧:

  • 若某类型对象数量少但保留大小极大 → 重点排查;
  • 对象过多但保留大小较小 → 可能是频繁分配导致的 GC 压力问题。

适用于分析内存泄漏、对象未释放或内存使用异常等问题。

内存泄漏检测

通过比对不同时间点的快照,可以发现:

  • 某些对象数量持续增长;
  • 旧对象仍被引用;
  • 某类实例占用比例异常。

3.3 线程分析

3.3.1 线程转储分析

如果怀疑线程死锁、阻塞、CPU 占用异常,可以使用 “获取线程转储” 功能。

在图中:

  • 左侧为所有线程的状态,如 RUNNABLE、WAITING、BLOCKED;
  • 右侧显示每个线程的调用栈;
  • 可以快速识别正在运行的线程与阻塞线程。

例如截图中的:

RMI TCP Connection(1)-127.0.0.1 处于 RUNNABLE 状态,调用栈显示正在执行 JMX 的方法调用。

这有助于排查:

  • 死锁(Deadlock)
  • 线程池卡死
  • 长时间 I/O 阻塞

3.4 CPU 与内存实时监控

可直接显示 CPU、堆内存、非堆内存、线程数量的动态变化。

图表含义:

图表 说明
CPU 实时 CPU 占用率,反映当前负载变化
堆内存 (Heap) JVM 堆使用量,监测是否有持续上涨的趋势
非堆内存 (Non-Heap) 包含类元数据、线程栈、本地缓存等
线程 (Threads) 线程数量变化,帮助判断并发问题

从截图可见,CPU 使用率维持在 2%~6% 间波动,堆内存约 17 MB,说明应用处于空闲或轻载状态。

四、总结

IntelliJ IDEA 内置的 Profiler 工具将强大的性能分析能力无缝集成到开发环境之中,有效降低了性能优化的技术门槛。通过其提供的 CPU 分析、内存分析与线程分析 三大功能,我们能够系统地应对响应迟缓、内存消耗异常及并发瓶颈等常见挑战。

性能分析实战建议:

  • 由表及里,层层深入: 当遇到接口响应慢时,先从 CPU 火焰图 或 调用树 开始,找到最耗时的“热点”方法。如果CPU不高但应用卡顿,则转向 内存分析,检查GC活动或内存泄漏。若怀疑并发问题,尝试用 线程转储 和 时间线 来排查。
  • 对比分析: 在进行重大代码变更前后,分别进行性能分析并对比结果,可以为优化效果提供可靠的数据支撑,方便评估优化效果。
  • 关注“黄色块”代码: 在火焰图中,优先关注代表自身业务代码的黄色块,它们通常是最有优化潜力的部分。
  • 结合日志与监控: 在分析一个复杂问题时,Profiler 能精准定位到是“哪一行代码”执行慢或消耗了大量内存。而要理解“为什么”会这样,我们通常需要:查看应用日志,了解当时执行了什么具体业务;再结合系统监控工具,观察整个请求链路和服务器资源状态。把这些信息综合起来,才能完整地还原问题全貌。

结语

性能优化不应是事故发生后的一次性补救,而应是贯穿于开发周期的最佳实践。IntelliJ IDEA Profiler 使得在日常开发中随时进行“性能快照”成为可能。通过熟练掌握并运用这一利器,开发者不仅能高效地扑灭线上的“性能大火”,更能从源头上编写出更高效、更健壮的代码。

文章目录
  1. 1. 一、前言:为什么要做性能分析?
  2. 2. 二、Profiler 简介与原理
  3. 3. 三、启动方式
  4. 4. 三、Profiler核心功能详解
    1. 4.1. 3.1 CPU性能分析
      1. 4.1.1. 3.1.1 火焰图(Flame Graph)
      2. 4.1.2. 3.1.2 调用树(Call Tree)
      3. 4.1.3. 3.1.3 方法列表(Method List)
      4. 4.1.4. 3.1.4 时间线(Timeline)
    2. 4.2. 3.2 内存分析
      1. 4.2.1. 3.2.1 捕获内存快照
    3. 4.3. 3.3 线程分析
      1. 4.3.1. 3.3.1 线程转储分析
    4. 4.4. 3.4 CPU 与内存实时监控
  5. 5. 四、总结
    1. 5.0.1. 性能分析实战建议:
    2. 5.0.2. 结语