CodeGym /课程 /JAVA 25 SELF /JVM 监控:JMX、VisualVM、Java Flight Recorder

JVM 监控:JMX、VisualVM、Java Flight Recorder

JAVA 25 SELF
第 63 级 , 课程 3
可用

1. JMX (Java Management Extensions):JVM 监控的心脏

监控就像对你的应用进行定期体检。日志可以比作日记,记录已经发生的一切;而监控是一组仪表,实时显示系统当前状态:温度、脉搏、血压、血糖以及其他对 JVM 至关重要的指标。

它帮助你了解实际使用了多少内存、是否存在泄漏、有多少线程在运行以及它们所处的状态——等待、运行还是被阻塞。你可以看到垃圾回收执行的频率、CPU 的负载,并能及时发现诸如内存或线程数突然增长等预警信号。

简而言之,日志讲述的是“已经发生了什么”,而监控展示的是“此时此刻正在发生什么”。

JMX 基础:是什么,有什么用

JMX 是 Java 的一项技术,允许你从内部观察应用的运行情况,甚至对其进行一定程度的管理。它通过特殊对象——MBean(Management Bean)来工作。可以把它理解为 JVM 内部的“传感器”和“开关”:有的用来显示系统状态,有的可以进行调节。

借助 JMX,你无需改动代码或重启应用,就能知道 JVM 当前分配了多少内存、有多少线程处于活动状态、垃圾回收耗时多少,以及更多信息。

其工作原理

JVM 中开箱即用地提供了大量 MBean,它们可以提供以下信息:

  • 内存(heapnon-heap);
  • 垃圾回收器(GC);
  • 线程;
  • 类(已加载与已卸载数量);
  • 甚至是 JVM 本身(版本、启动参数)。

JMX 就像汽车的仪表盘。 你能看到速度、转速、发动机温度——这一切都通过标准的“传感器”(MBean)提供。

如何访问 JMX

最简单的方式是使用 JDK 自带的标准工具 JConsole

启动 JConsole

  1. 打开终端/命令行。
  2. 执行命令:
    jconsole
    
  3. 选择你想监控的 Java 进程(例如你的应用)。

JConsole 将通过 JMX 连接到 JVM,并展示图表和表格:内存使用、线程数量、垃圾回收活动等。

示例:查看内存与线程

JConsole 中打开 "Memory""Threads" 选项卡。你会看到已用内存的变化、当前存活线程数、哪些线程处于活动状态、哪些在等待。

自定义 MBean

你可以创建自己的 MBean 来监控自定义指标(例如已处理订单的数量)。不过这是进阶内容:标准的 MBean 已经提供了非常多的信息。

2. VisualVM — 可视化监控与性能剖析

如果说 JConsole 是“仪表盘”,那么 VisualVM 就是一整个诊断中心,配有 X 光、核磁共振(MRI)和血液分析。它不仅能监控,还能对应用进行剖析,抓取 heap dump,分析内存泄漏,并查看哪些方法最耗时。

安装与启动 VisualVM

  • VisualVMJDK 提供(通常名为 jvisualvm),也可以在 visualvm.github.io 下载最新版本。
  • 启动命令:
    jvisualvm
    
  • 启动后你会看到本机上所有正在运行的 Java 进程列表。

连接到进程

  1. 在列表中找到你的进程(例如 MainMyApp)。
  2. 双击它——会打开该进程的信息页。
  3. 完成!现在你可以看到:
    • 实时的 CPU 与内存使用。
    • 线程数量及其状态。
    • 已加载类的列表。
    • 抓取 heap dumpthread dump 的入口。

VisualVM 的主要功能

借助 VisualVM,你可以观察内存的使用情况——包括 heapnon-heap。图表能显示内存消耗是在增长还是趋于稳定。想要检查垃圾回收是否工作正常,点击 "Perform GC" 按钮——JVM 会立即尝试回收内存。你可以生成 heap dump(内存快照)并分析它来定位泄漏。

它也能展示线程状态:多少线程在运行、哪些在工作、哪些在等待或被阻塞。如果发生了 deadlockVisualVM 能帮助检测并展示互相等待的关系。

对于更深入的分析,可以使用性能剖析:你能看到“热点”方法,即那些最耗费 CPU 时间或内存的方法。这对于诊断性能意外下降非常有用。

示例:监控一个小程序

public class MemoryLeakDemo {
    public static void main(String[] args) throws InterruptedException {
        List<byte[]> memoryConsumers = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            memoryConsumers.add(new byte[1024 * 1024]); // 1 MB
            Thread.sleep(100); // 稍微等待一下,让曲线更平滑
        }
        System.out.println("完成!别忘了在 VisualVM 里查看 :)");
        Thread.sleep(60000); // 保持应用运行以便分析
    }
}

现在:

  1. 运行程序。
  2. 打开 VisualVM,连接到该进程。
  3. 观察内存使用如何增长。
  4. 抓取 heap dump,找出占用内存的数组。

3. Java Flight Recorder (JFR):JVM 的“黑匣子”

什么是 JFR

Java Flight Recorder 是内置于 JVM 的事件采集工具。它是“黑匣子”:JFR 会记录 JVM 中发生的事情,方便之后定位瓶颈或事故原因。

JFR 会采集:

  • GC 事件;
  • 线程信息;
  • 方法调用频率与时间剖析;
  • 停顿与延迟;
  • 异常与错误。

如何启用 JFR

从 Java 11 起,JFR 已内置在 OpenJDK 中。

使用 JFR 启动

java -XX:StartFlightRecording=filename=recording.jfr,duration=60s,settings=profile -jar MyApp.jar
  • filename=recording.jfr — 保存文件的位置。
  • duration=60s — 录制时长。
  • settings=profile — 详细程度(defaultprofilecontinuous)。

查看结果

用于分析 .jfr 文件的工具是 JDK Mission ControlJMC):

  1. 下载 JMCjdk.java.net/jmc
  2. 打开文件 recording.jfr
  3. 查看图表、热点方法、GC 停顿以及线程活动。

示例:录制“黑匣子”

  1. 使用 JFR 启动应用(见上面的命令)。
  2. 打开 JDK Mission Control,加载录制文件。
  3. 评估 CPU/内存热点、垃圾回收频率以及活跃线程数量。

4. 实践:监控一个应用

import java.util.ArrayList;
import java.util.List;

public class MonitoringExample {
    public static void main(String[] args) throws InterruptedException {
        List<byte[]> memory = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            memory.add(new byte[2 * 1024 * 1024]); // 2 MB
            Thread.sleep(500);
        }
        // 启动一个线程
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println("后台线程在运行...");
                } catch (InterruptedException e) {
                    break;
                }
            }
        }).start();

        Thread.sleep(20000); // 保持应用运行以便监控
    }
}

操作:

  • 运行程序。
  • 打开 VisualVM,找到该进程,查看内存图和线程。
  • 尝试抓取 heap dumpthread dump
  • 进阶:使用 JFR 启动,并在 JMC 中查看结果。

5. 实用细节

监控工具对比表

工具 适用场景 如何启动 特点
JConsole (JMX) JVM 基本指标、线程、GC
jconsole
简单,随 JDK 提供
VisualVM 监控、性能剖析、heap dump
jvisualvm
图表、内存分析、CPU
Java Flight Recorder JVM 事件的深度分析
java -XX:StartFlightRecording...
在 JMC 中分析,“黑匣子”
JDK Mission Control 查看 JFR 文件 独立程序 详细分析与报告

建议

  • 不仅在生产环境监控,也要在测试阶段监控。 这样可以更早发现内存泄漏和“挂起”的线程。
  • Heap dump 并不可怕! 在怀疑内存泄漏时抓取内存转储,并在 VisualVM 中分析它。
  • 大胆尝试使用 JFR。 即便一开始不太明白,事件与图表也能帮助定位瓶颈。
  • 可以以编程方式使用 JMX。 例如将指标发送到 Prometheus/Grafana
  • 性能剖析不宜长期开启。 按需启用分析器,否则应用可能变慢。

6. JVM 监控中的常见错误

错误 1:完全不做监控。 许多新手认为只要应用“能跑”就一切正常。实际上,内存和线程问题常常在高负载或运行一段时间后才显现。别偷懒,至少定期打开 VisualVM/JConsole 看一看。

错误 2:在大型应用上未做准备就抓取 heap dump。 大型应用的 heap dump 可能有数 GB,并会让进程“冻结”数秒。尽量在测试环境或生产的低峰时段进行。

错误 3:忽视 GC 和线程指标。 如果 GC 占用的时间比例持续偏高——这是危险信号!如果线程数量稳定增长——请排查线程泄漏。

错误 4:不分析监控结果。 仅打开 VisualVM 还不够。看看哪些对象占据了内存,哪些方法“吃掉”了最多的 CPU,为何会出现 deadlock。分析堆栈跟踪与根因。

错误 5:在生产环境盲目使用性能分析器。 性能剖析可能显著拖慢应用。只在诊断时按需开启,而不是“长期运行”。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION