JVM内存模型核心结构
JVM内存模型主要划分为堆、虚拟机栈、方法区和程序计数器等区域,各区域承担不同职责且具有独特特性。
堆(Heap)
- 存储对象实例和数组,所有线程共享
- 分为新生代(Eden、Survivor0/1)和老年代
- 默认最大容量为物理内存1/4,可通过
-Xmx参数调整 - 发生OOM时抛出
OutOfMemoryError
虚拟机栈(Stack)
- 线程私有,生命周期与线程相同
- 存储栈帧(局部变量表、操作数栈、动态链接、方法出口)
- 栈深度超过限制时抛出
StackOverflowError - 可通过
-Xss参数调整栈大小(默认1MB)
方法区(Method Area)
- 存储类信息、常量、静态变量、JIT编译代码
- JDK8后由元空间(Metaspace)实现,使用本地内存
- 触发Full GC时回收类型信息
- 大小通过
-XX:MetaspaceSize参数配置
垃圾回收机制
分代收集理论
- 新生代采用复制算法(Minor GC)
- 老年代采用标记-清除/整理算法(Major GC)
- 触发条件:新生代Eden区满触发Minor GC,老年代空间不足触发Full GC
GC算法实现
java
// 引用计数法(存在循环引用问题)
class Object {
int refCount = 0;
}
// 可达性分析算法(JVM实际采用)
// GC Roots包括:虚拟机栈引用、静态变量、常量、JNI引用
垃圾收集器类型
- Serial:单线程STW,适合客户端
- Parallel Scavenge:吞吐量优先
- CMS:低延迟,JDK9废弃
- G1:区域化分代,JDK9默认
- ZGC:TB级堆,<10ms停顿
内存参数配置示例
常见JVM参数
shell
-Xms4g -Xmx4g # 堆初始/最大内存
-XX:NewRatio=2 # 老年代/新生代比例
-XX:SurvivorRatio=8 # Eden/Survivor比例
-XX:+UseG1GC # 启用G1收集器
内存溢出场景分析
堆溢出
java
// 持续创建大对象
List<byte[]> list = new ArrayList<>();
while(true) {
list.add(new byte[1024*1024]);
}
栈溢出
java
// 递归调用无终止条件
void stackOverflow() {
stackOverflow();
}
方法区溢出
- 动态生成大量类(如CGLib)
- 大量JSP动态编译
- 大量反射调用
监控工具建议
jstat -gcutil [pid]实时GC统计jmap -heap [pid]堆内存分析- VisualVM图形化监控
- MAT内存分析工具定位泄漏对象
通过合理配置内存参数和选择垃圾收集器,可优化应用性能。建议根据应用特点(吞吐量/延迟敏感)选择收集器,并通过压测验证配置效果。