Java 内存区域
在查看内存之前,最好先了解一下 Java 内存的主要区域,这有助于你理解各种工具输出的含义:

-
堆内存:
- 作用:存放对象实例和数组,是垃圾收集器管理的主要区域。
- 查看:这是我们最常关注的部分,关注其已使用、最大和空闲容量。
-
非堆内存 / 元空间:
- 作用:存放类元数据、 JIT(即时编译器)编译后的代码缓存、线程等。
- 查看:关注其使用情况,如果这里满了也可能导致
OutOfMemoryError。
-
线程栈:
- 作用:每个线程在创建时都会分配一个私有的栈空间,用于存储局部变量、方法调用等。
- 查看:关注线程数量和单个栈大小,如果线程过多或单个栈过大,会消耗大量内存。
使用 jps 和 jstat (JDK 内置工具)
这是最常用、最轻量级的方法,无需安装任何额外软件。

步骤 1: 找到 Java 进程 ID
你需要查看当前系统中有哪些 Java 进程在运行。
# 显示所有 Java 进程的 ID 和主类名 jps # 或者显示更详细的信息,包括 jar 包路径 jps -l
输出示例:
12345 com.example.MyApplication
67890 org.apache.catalina.startup.Bootstrap
9876 sun.tools.jps.Jps
这里的 12345 和 67890 就是你需要关注的 Java 进程 ID。
步骤 2: 使用 jstat 查看内存统计
jstat 是一个强大的性能监控工具,可以实时查看 JVM 的各种运行时数据。
查看堆内存使用概览
# jstat -gc <PID> <interval> <count> # PID: Java 进程 ID # interval: 采样间隔(毫秒) # count: 采样次数,不填则持续采样 # 示例:每 1 秒查看一次 PID 为 12345 的进程的 GC 情况,共 10 次 jstat -gc 12345 1000 10
输出解读:
S0C S1C ... UGCM UGCT ... EU OU ... YGC YGCT ... GCT ...
512.0 512.0 ... 0.00 0.000 ... 26.43 6.86 ... 2 0.050 ... 0.050 ...
512.0 512.0 ... 0.00 0.000 ... 26.43 6.86 ... 2 0.050 ... 0.050 ...
...
S0C/S1C: Survivor 0 和 Survivor 1 区的容量(Capacity)。EC: Eden 区的容量。OU: Old 区已使用的大小。PU: Perm / Metaspace 区已使用的大小 (在 JDK 8+ 中为 Metaspace)。YGC: Young GC 次数。YGCT: Young GC 耗时。FGC: Full GC 次数。FGCT: Full GC 耗时。GCT: 总 GC 耗时。EU: Eden 区已使用的大小。EU: Eden 区已使用的大小。
查看内存使用摘要
如果你想快速了解堆内存的总体情况,可以使用 -gccapacity 选项。
jstat -gccapacity 12345
输出解读:
NGCMN NGCMX NGC S0C S1C ...
8192.0 8192.0 8192.0 512.0 512.0 ...
NGCMN/NGCMX/NGC: New Generation (新生代) 的最小、最大和当前容量。OGCMN/OGCMX/OGC: Old Generation (老年代) 的最小、最大和当前容量。MetaspaceCM: Metaspace 的最大容量。
使用 jmap (JDK 内置工具)
jmap 主要用于生成 JVM 的内存转储快照,或者查看堆内存的详细信息。
生成堆转储文件
当怀疑内存泄漏时,可以使用 jmap 生成一个 .hprof 文件,然后用工具(如 Eclipse MAT, VisualVM)进行分析。
# jmap -dump:format=b,file=<filename.hprof> <PID> # format=b 表示二进制格式 # 示例:为 PID 12345 生成堆转储文件 heapdump.hprof jmap -dump:format=b,file=heapdump.hprof 12345
注意:生成堆转储是一个比较重的操作,可能会让 JVM 暂停,请在业务低峰期执行。
查看堆内存的直方图
可以查看堆中对象的数量和大小分布,有助于快速定位占用内存最多的对象类型。
# jmap -histo <PID> # 如果想看到所有类(包括JDK内部类),加上 -all 选项 # 示例:查看 PID 12345 的对象直方图 jmap -histo 12345
输出解读:
num #instances #bytes class name
---------------------------------------
1 150000 24000000 [C
2 50000 16000000 java.lang.String
3 10000 8000000 com.example.MyObject
...
#instances: 对象实例数量。#bytes: 占用总字节数。class name: 类名。
使用 top / htop (系统级工具)
这些是通用的 Linux 系统进程监控工具,可以快速查看一个进程占用了多少物理内存。
# 按内存使用率排序 (P: 按 CPU 排序, M: 按 内存 排序) top # 或者使用更友好的 htop htop
然后按 M 键,找到你的 Java 进程,你会看到 RES (或 RESIDENT) 列,这表示该进程占用的物理内存大小。
- 优点:快速、直观,无需任何 JDK 工具。
- 缺点:无法区分 Java 堆内存、非堆内存等内部细节,只知道总的内存占用。
使用 jcmd (JDK 内置工具,JDK 7+)
jcmd 是一个多功能命令行工具,可以替代 jps, jstat, jmap 等多个工具,它通过向 JVM 发送命令来获取信息。
列出所有 Java 进程
jps -l # 或者 jcmd
查看内存使用情况
# jcmd <PID> GC.heap_info jcmd 12345 GC.heap_info
查看 GC 统计信息
# jcmd <PID> GC.class_histogram # 功能与 jmap -histo 类似 jcmd 12345 GC.class_histogram # jcmd <PID> GC.info # 功能与 jstat -gc 类似 jcmd 12345 GC.info
使用可视化工具 (图形界面)
如果你不习惯命令行,可以使用图形化的监控工具。
VisualVM
VisualVM 是 JDK 自带的一款强大的监控、故障排查和性能分析工具。
- 启动:在终端输入
jvisualvm。 - 连接:它会自动扫描并显示本地所有运行的 Java 应用,你也可以添加远程主机。
- 监控:
- 监控:实时查看 CPU、堆内存、类、线程等信息。
- Sampler:可以抽样分析 CPU 和内存,查看哪个方法/对象最耗时/耗内存。
- Visual GC:一个强大的插件,可以实时、图形化地展示 GC 的各个区域的活动情况,非常直观。
JConsole
JConsole 是另一个 JDK 自带的简单监控工具。
- 启动:在终端输入
jconsole。 - 连接:选择要监控的本地进程。
- 监控:提供内存、线程、类等基本信息的图表视图,但比 VisualVM 简单。
总结与推荐
| 方法 | 命令 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
jps + jstat |
jps, jstat -gc |
最常用、轻量级、信息详细、无需安装 | 命令行操作,需要解读输出 | 日常监控和快速检查,持续观察内存趋势和 GC 情况。 |
jmap |
jmap -dump, jmap -histo |
能生成快照进行分析,查看对象分布 | 生成快照会暂停 JVM,较重 | 内存泄漏分析,需要深入堆内部查看对象时。 |
top / htop |
top (按 M 排序) |
最快速、系统级通用 | 无法区分 JVM 内部内存区域 | 快速检查 Java 进程总的物理内存占用。 |
jcmd |
jcmd, jcmd ... GC.heap_info |
功能强大,统一入口,可远程 | 相对较新,命令参数较多 | JDK 7+ 环境,需要执行多种 JVM 命令。 |
| VisualVM | jvisualvm |
图形化界面、功能全面、集成 Visual GC | 需要启动 GUI,略显笨重 | 深度分析和实时监控,特别是需要图形化查看 GC 时。 |
实践建议
- 日常巡检:使用
top或htop快速查看 Java 进程的总内存占用,如果发现异常,再使用jstat -gc <PID>深入查看堆内存和 GC 情况。 - 性能调优/问题排查:启动
VisualVM,利用其图形化界面(特别是 Visual GC 插件)实时观察 JVM 内部状态,结合jmap -histo分析对象。 - 怀疑内存泄漏:使用
jmap -dump生成堆快照,然后用 Eclipse MAT 等工具进行分析,找到无法被回收的对象。
希望这份详细的指南能帮助你更好地在 Linux 上监控 Java 应用的内存!
