在 CentOS 上发现 Java 进程占用内存很高,通常不是“内存泄漏”那么简单,而是和 JVM 内存模型、系统统计口径、参数配置 有关。下面按常见原因给你系统讲一下。
先确认你是怎么看的:
| 查看方式 | 看到的是什么 |
|---|---|
top |
RES(常驻内存) |
free -h |
系统整体内存 |
ps |
RSS |
jmap |
JVM 堆内存 |
jstat |
JVM 各区域 |
⚠️ top 里的 RES ≠ Java 堆内存
CentOS 上 Java 默认:
MaxHeap = 物理内存的 1/4
比如:
但还有:
✅ 解决:
-Xms2g -Xmx2g
Java 8+ 用 Metaspace 替代 PermGen:
✅ 查看:
jstat -gcmetacap <pid>
✅ 限制:
-XX:MaxMetaspaceSize=256m
每个 Java 线程:
1000 个线程 ≈ 1GB 内存
✅ 查看线程数:
ps -eLf | grep java | wc -l
✅ 调整:
-Xss256k
很多组件用:
它们 不在堆里,但吃内存
✅ 限制:
-XX:MaxDirectMemorySize=512m
这是 CentOS 经典问题:
top 还是很高✅ 验证:
cat /proc/<pid>/smaps | grep Rss
✅ 解决:
export MALLOC_ARENA_MAX=4
表现:
✅ 排查:
jmap -histo <pid>
jmap -dump:live,format=b,file=heap.hprof <pid>
用:
物理内存:16G
Java 配置:默认
top 显示:RES 6G
实际堆:2G
其余:元空间 + 线程 + 堆外 + glibc
✅ 这不是异常
-Xms2g
-Xmx2g
-Xss256k
-XX:MaxMetaspaceSize=256m
-XX:MaxDirectMemorySize=512m
-XX:+UseG1GC
你可以贴:
top / free -h 截图我可以帮你算 哪些是正常、哪些是异常 ✅