JVM内存模型主要由堆、栈、方法区/元空间等区域构成:堆是线程共享的最大区域,分为新生代(Eden+S0+S1)和老年代,存储对象实例,是垃圾回收的主要场所;栈为线程私有,存储局部变量和方法调用信息;方法区在Java 8前以永久代(PermGen)形式存在,Java 8后被使用本地内存的元空间(Metaspace)替代,用于存储类元数据、常量和静态变量。垃圾回收机制通过可达性分析识别无用对象,采用分代收集策略——新生代使用复制算法,老年代使用标记-清除或标记-整理算法,并随着JDK版本演进从Serial、CMS发展到G1、ZGC等低延迟收集器,目标是在保证应用吞吐量的同时最小化停顿时间。

一、JVM内存模型

JVM内存主要分为以下几个区域:

1. 堆(Heap)

  • 最大内存区域,被所有线程共享
  • 存放对象实例数组
  • 垃圾回收的主要区域
  • 分为:
    • 新生代(Young Generation):包括Eden区和两个Survivor区(S0/S1)
    • 老年代(Old Generation)
  • 可通过-Xms(初始堆大小)和-Xmx(最大堆大小)参数调整

2. 栈(Stack)

  • 线程私有,生命周期与线程相同
  • 每个方法执行时创建栈帧,包含:
    • 局部变量表
    • 操作数栈
    • 动态链接
    • 方法出口
  • 可能抛出StackOverflowError或OutOfMemoryError
  • 大小可通过-Xss参数设置

3. 方法区(Method Area)

  • 线程共享的内存区域
  • 存储:
    • 已加载的类信息
    • 常量
    • 静态变量
    • JIT编译后的代码
  • Java 8之前:实现为永久代(PermGen)
  • Java 8及以后:被元空间(Metaspace) 取代

4. 元空间(Metaspace)

  • 取代永久代,使用本地内存而非JVM内存
  • 存储类的元数据
  • 优势:
    • 大小仅受限于系统可用内存
    • 避免了永久代内存溢出问题
  • 通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize控制

5. 程序计数器

  • 线程私有,最小的内存区域
  • 记录当前线程执行的字节码指令地址
  • 唯一不会发生OOM的区域

6. 本地方法栈

  • 与虚拟机栈类似,服务于Native方法

二、垃圾回收机制

1. 垃圾识别

  • 可达性分析算法:从GC Roots对象集出发,无法到达的对象即为垃圾
  • GC Roots包括:
    • 虚拟机栈中引用的对象
    • 方法区中静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中JNI引用的对象

2. 垃圾回收算法

  • 标记-清除(Mark-Sweep)

    • 先标记,再清除
    • 问题:内存碎片化
  • 复制(Copying)

    • 适用于新生代
    • 将存活对象复制到另一块空间
    • Eden:S0:S1通常比例为8:1:1
  • 标记-整理(Mark-Compact)

    • 适用于老年代
    • 让存活对象向一端移动,清理边界外内存
  • 分代收集(Generational Collection)

    • 基于"弱代假说":大多数对象朝生夕死
    • 新生代:采用复制算法
    • 老年代:采用标记-清除或标记-整理算法

3. 垃圾回收器

  • Serial/Serial Old:单线程,适合客户端应用

  • ParNew:Serial的多线程版,可与CMS配合

  • Parallel Scavenge/Parallel Old:关注吞吐量

  • CMS(Concurrent Mark Sweep)

    • 低停顿,并发执行
    • 步骤:初始标记→并发标记→重新标记→并发清除
    • 问题:CPU敏感、内存碎片
  • G1(Garbage First)

    • 将堆划分为多个Region
    • 可预测停顿时间
    • 优先回收垃圾最多的Region
  • ZGC/Shenandoah

    • JDK11+引入
    • 超低延迟(≤10ms)
    • 支持TB级堆内存

4. GC触发条件

  • Minor GC/YGC:Eden区满时触发,回收新生代
  • Major GC/Full GC:老年代或元空间满时触发
    • 频率低,耗时长
    • 严重影响应用性能

5. JVM参数调优示例

# 设置堆大小
-Xms4g -Xmx4g
# 设置新生代大小
-Xmn2g
# 选择G1收集器
-XX:+UseG1GC
# 设置最大停顿时间目标
-XX:MaxGCPauseMillis=200
# 设置元空间大小
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# 打印GC日志
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log

在实际应用中,应根据应用特点、硬件配置和性能需求,选择合适的垃圾回收器和参数配置,以达到最佳性能表现。