1. 概述
本文将介绍如何使用 纯 JDK 提供的核心 API 来监控 Java 应用的关键运行指标,主要包括:
- ✅ 磁盘空间使用情况
- ✅ JVM 内存使用
- ✅ 线程与 CPU 时间消耗
我们不会引入任何第三方库,所有示例均基于 JDK 自带的 java.io.File
和 java.lang.management.ManagementFactory
类实现。
最后还会简单提一下如何用 Java Profiler 做更全面的监控,避免自己重复造轮子。
2. File 类简介
File
类是对文件或目录路径的抽象,不仅能操作文件,还能获取文件系统信息,并保证跨平台路径兼容性(比如 Windows 用 \
,Linux 用 /
)。
本文中,我们将用它来获取系统磁盘的总空间、可用空间等信息,适用于 Windows 和 Linux 环境。
3. ManagementFactory 简介
ManagementFactory
是 JDK 提供的一个工厂类,用于获取 JVM 的各种 管理 Bean(MXBean),这些 Bean 暴露了 JVM 内部的运行时数据。
我们重点关注以下两个:
3.1 MemoryMXBean
代表 JVM 内存系统的管理接口。JVM 启动后会自动创建一个实例,通过 ManagementFactory.getMemoryMXBean()
可获取。
可用于监控堆内存的使用、初始大小、最大限制等。
3.2 ThreadMXBean
代表 JVM 线程系统的管理接口,通过 ManagementFactory.getThreadMXBean()
获取。
它可以获取当前所有线程的 ThreadInfo
对象,进而分析线程状态、CPU 占用时间等,对排查死锁、线程阻塞等问题非常有用。
4. 监控磁盘使用情况
使用 File
类可以轻松获取指定磁盘分区的空间信息。下面以 Windows 的 C 盘为例:
File cDrive = new File("C:");
System.out.println(String.format("Total space: %.2f GB",
(double)cDrive.getTotalSpace() / 1073741824));
System.out.println(String.format("Free space: %.2f GB",
(double)cDrive.getFreeSpace() / 1073741824));
System.out.println(String.format("Usable space: %.2f GB",
(double)cDrive.getUsableSpace() / 1073741824));
✅ 输出示例:
Total space: 476.94 GB
Free space: 210.32 GB
Usable space: 210.32 GB
⚠️ 注意:
getTotalSpace()
:磁盘总容量getFreeSpace()
:未被占用的空间getUsableSpace()
:当前用户可使用的空间(可能受权限或保留空间影响)
在 Linux 上只需换成根目录 /
即可:
File root = new File("/");
System.out.println(String.format("Total space: %.2f GB",
(double)root.getTotalSpace() / 1073741824));
System.out.println(String.format("Free space: %.2f GB",
(double)root.getFreeSpace() / 1073741824));
System.out.println(String.format("Usable space: %.2f GB",
(double)root.getUsableSpace() / 1073741824));
📌 小贴士:返回值单位是字节,我们除以 1073741824
(即 1024³)转为 GB,提升可读性。
5. 监控 JVM 内存使用
通过 MemoryMXBean
可以实时获取 JVM 堆内存的使用情况:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
System.out.println(String.format("Initial memory: %.2f GB",
(double)memoryMXBean.getHeapMemoryUsage().getInit() / 1073741824));
System.out.println(String.format("Used heap memory: %.2f GB",
(double)memoryMXBean.getHeapMemoryUsage().getUsed() / 1073741824));
System.out.println(String.format("Max heap memory: %.2f GB",
(double)memoryMXBean.getHeapMemoryUsage().getMax() / 1073741824));
System.out.println(String.format("Committed memory: %.2f GB",
(double)memoryMXBean.getHeapMemoryUsage().getCommitted() / 1073741824));
✅ 输出示例:
Initial memory: 0.25 GB
Used heap memory: 0.08 GB
Max heap memory: 4.00 GB
Committed memory: 0.50 GB
📌 各字段含义:
字段 | 说明 |
---|---|
init |
JVM 启动时申请的初始堆内存 |
used |
当前已使用的堆内存 |
max |
堆内存最大值,超过会抛 OutOfMemoryError |
committed |
JVM 向操作系统保证可用的内存(已提交) |
⚠️ 注意:max
受 -Xmx
参数限制,若未设置,默认为系统内存的 1/4 左右。
6. 监控线程与 CPU 使用
ThreadMXBean
能获取所有线程的运行时信息,包括状态、CPU 时间等,适合做性能分析或排查线程泄漏。
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
for (Long threadID : threadMXBean.getAllThreadIds()) {
ThreadInfo info = threadMXBean.getThreadInfo(threadID);
System.out.println("Thread name: " + info.getThreadName());
System.out.println("Thread State: " + info.getThreadState());
System.out.println(String.format("CPU time: %s ns",
threadMXBean.getThreadCpuTime(threadID)));
}
✅ 输出示例:
Thread name: main
Thread State: RUNNABLE
CPU time: 123456789 ns
📌 关键点:
getAllThreadIds()
:获取当前所有线程 IDgetThreadInfo(threadId)
:获取线程详细信息getThreadCpuTime(threadId)
:返回线程使用的 CPU 时间(纳秒),仅当 CPU 时间监控开启时有效(默认开启)
💡 实际应用中,可定期采样 CPU 时间差值,计算线程的 CPU 占用率。
7. 使用 Profiler 监控指标(推荐方式)
上面的方法虽然简单,但属于“手动打点”,适合轻量级监控或嵌入到日志中。
但如果你需要更全面、实时的分析,强烈建议使用 Java Profiler,它们能无侵入地监控:
- ✅ 内存分配与 GC 行为
- ✅ 线程阻塞、死锁检测
- ✅ 方法调用耗时(CPU Profiling)
- ✅ 类加载、JVM 参数等
常见工具:
- VisualVM:JDK 自带(Java 6 起),免费、轻量,支持本地/远程监控
- JConsole:同样 JDK 自带,功能较基础
- JProfiler、YourKit:商业工具,功能强大,适合生产问题排查
- Async-Profiler:开源高性能采样器,支持火焰图生成
📌 开发阶段建议在 IDE 中安装 VisualVM 插件,简单粗暴地看内存和线程状态,比写代码查 ManagementFactory
快多了。
8. 总结
本文介绍了如何使用 JDK 原生 API 监控 Java 应用的关键指标:
- ✅
File
类:快速获取磁盘空间(跨平台) - ✅
MemoryMXBean
:查看 JVM 堆内存使用 - ✅
ThreadMXBean
:分析线程状态与 CPU 时间 - ✅ Profiler:生产环境推荐方案,无需编码即可全面监控
💡 踩坑提醒:
getUsableSpace()
在某些文件系统上可能和getFreeSpace()
不一致(如保留空间)getThreadCpuTime()
返回null
?检查是否启用了 CPU 时间监控max
内存可能小于物理内存,受-Xmx
限制
对于线上服务,建议结合 Micrometer + Prometheus 做长期指标采集,而本文方法更适合临时排查或嵌入健康检查接口。