Files
StudyDiary-20261009/02-学习笔记/Tips/Linux 排查Java进程内存过高完整方法.md
CrazyJasonwell e97be9ac8c commit all
2026-10-09 22:06:40 +08:00

159 lines
3.7 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Linux 排查Java进程内存过高完整方法
# Linux 排查 Java 进程内存过高完整方法
## 一、先找到占用高内存的 Java 进程
### 方式 1:top(最常用,实时查看)
```bash
top
```
- 按 `M` 大写 M:**按内存占用降序排序**
- 找到 `COMMAND` 列是 `java` 的行,记下 PID(第一列数字)
### 方式 2:htop(更友好,需要安装)
```bash
htop
```
### 方式 3:ps 一次性列出所有 java 进程,看 RSS \(物理内存\)
```bash
ps -ef | grep java
# 带内存占用版本
ps aux | grep java
```
> 字段说明:`%MEM` 内存占比,`RSS` 实际物理内存(单位 KB)
>
>
### 方式 4:只看 java 进程,排序内存
```bash
ps aux | grep -E 'java' | grep -v grep | sort -k4 -nr
```
---
## 二、拿到 PID 后,查看 JVM 内部内存情况(JDK 自带工具)
> ⚠️ 前提:运行 java 的用户和执行 jps/jstat/jmap 的用户一致,否则会权限失败
>
>
### 1\. jps 快速列出所有 Java 进程 \+ PID
```bash
jps -l
```
`-l`:打印完整主类名,方便区分是哪个 Java 应用
### 2\. jstat 持续监控 JVM 堆内存变化(判断是否内存泄漏)
```bash
# 每1秒输出一次,持续观察,PID替换成你的java进程号
jstat -gc <PID> 1000
```
重点看这几列:
- `S0C,S1C`:Survivor 区容量
- `EC,OC`:Eden、Old 老年代容量
- `OU`:Old 区已使用大小
> 如果 **OU 持续上涨,Full GC 频繁但内存释放很少 → 大概率内存泄漏**
>
>
### 3\. jmap 查看堆内存快照(dump 内存文件,事后分析)
```bash
# 生成堆dump文件(会短暂STW,生产环境谨慎操作)
jmap -dump:format=b,file=heapdump.hprof <PID>
```
得到 `heapdump.hprof` 文件,可以下载到本地,用 **MAT\(Memory Analyzer Tool\)** 分析,定位是哪个对象占用大量内存。
查看堆内存概况(不用生成文件):
```bash
jmap -heap <PID>
```
输出 JVM 堆配置:新生代、老年代大小,GC 收集器类型。
查看对象统计:
```bash
jmap -histo <PID>
```
列出所有类实例数量、占用内存,找出占用最多的类。
### 4\. jstack 查看线程栈(排查是否线程堆积间接导致内存暴涨)
```bash
jstack <PID>
```
用来查找死锁、大量等待线程。
---
## 三、查看进程级详细内存(Linux 系统层面,区分 JVM 堆 / 非堆)
```bash
# 查看进程smaps,详细内存分布
cat /proc/<PID>/smaps
```
或者用 `pmap`
```bash
pmap -x <PID>
```
可以看到:堆内存、栈、共享库占用。
## 四、快速排查思路总结
1. `top` / `ps aux` → 确认是 Java 进程占用高,拿到 PID
2. `jstat -gc PID 1000` → 观察 GC 行为,判断是内存泄漏还是堆配置太小
3. `jmap -heap PID` → 看 JVM 堆参数是否合理(Xmx/Xms)
4. `jmap -dump` 导出堆快照,MAT 分析定位泄漏对象
5. `jstack` 辅助排查线程问题
## 五、常见原因
1. **内存泄漏**:代码创建对象没有释放(集合持续 add 不清理)
2. JVM 参数不合理:`-Xmx` 设置太大,吃掉大量宿主机内存
3. 堆外内存(DirectBuffer)占用:jmap 看不到堆外内存,需要额外排查
4. 并发请求过高,正常业务内存开销
## 六、小提示
- 如果是容器环境(docker),`top`看到的是容器内视图,宿主机需要额外查看
- dump 堆文件会占用磁盘空间,hprof 文件体积可能很大
- 如果 JDK 是精简版(没有自带 jmap/jstat),需要安装完整 JDK 或者使用`arthas`(阿里开源 Java 诊断工具)
如果你需要,我可以给你一份 **Arthas 一键排查命令集**,不需要依赖 JDK 自带工具。
> (注:部分内容由豆包工作 AI 生成)