JVM 与内存 整理
JVM 内存区域:先分清规范与实现
堆、栈、元空间,以及为什么 Xmx 不是整个 Java 进程的内存。
先回答:堆设置为 640MB,为什么进程用的内存可能更多?
最大堆内存只是进程内存的一部分。Java 进程还会使用线程栈、类元数据、代码缓存、直接内存和其他本地内存等。Xmx 不能作为整个进程内存占用的硬上限。
运行时数据区先按规范理解
JVM 规范描述了堆、方法区、运行时常量池、虚拟机栈、本地方法栈和程序计数器等概念。堆和方法区由线程共享,栈及程序计数器等与线程执行相关。
规范中的方法区不应直接等同于某个实现版本的“永久代”或“元空间”。HotSpot 在 JDK 8 中以元空间存放类元数据,它使用本地内存,是实现选择的一部分。
栈和堆回答到什么程度
方法调用对应栈帧,涉及局部变量、操作数栈等;对象通常在堆上分配。讨论逃逸分析或标量替换时,要区分语义模型与编译器优化,不能把优化描述成所有对象都必然在栈上分配。
栈深度过大可能出现 StackOverflowError。OutOfMemoryError 可能来自不同内存区域,应先看具体错误信息和运行参数。
小内存服务器上的检查顺序
- 先看系统可用内存、进程总内存和堆使用情况,不只盯 Xmx。
- 确认线程数量、元空间、直接内存和连接池等是否有合理边界。
- 根据现场选择 jcmd、GC 日志、堆转储等手段;转储和诊断也可能占用磁盘或影响服务。
- 先保留证据,再决定是参数不足、流量变化还是持续泄漏。
延伸阅读
以上为个人整理。涉及版本实现和线上使用时,请结合对应文档与实际测试判断。