# 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 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 ``` 得到 `heapdump.hprof` 文件,可以下载到本地,用 **MAT\(Memory Analyzer Tool\)** 分析,定位是哪个对象占用大量内存。 查看堆内存概况(不用生成文件): ```bash jmap -heap ``` 输出 JVM 堆配置:新生代、老年代大小,GC 收集器类型。 查看对象统计: ```bash jmap -histo ``` 列出所有类实例数量、占用内存,找出占用最多的类。 ### 4\. jstack 查看线程栈(排查是否线程堆积间接导致内存暴涨) ```bash jstack ``` 用来查找死锁、大量等待线程。 --- ## 三、查看进程级详细内存(Linux 系统层面,区分 JVM 堆 / 非堆) ```bash # 查看进程smaps,详细内存分布 cat /proc//smaps ``` 或者用 `pmap` ```bash pmap -x ``` 可以看到:堆内存、栈、共享库占用。 ## 四、快速排查思路总结 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 生成)