Java JVM 内存模型与对象
更新时间:2026-08-25。本文是
languages/java/主题第 ② 篇。Java 的内存由 JVM 托管——理解运行时数据区、对象布局、GC 回收,你才能看懂内存占用、调好 JVM 参数、排查内存泄漏。
本文要回答的问题
- Java 对象创建时发生了什么?运行时数据区怎么划分?
- GC 是怎么判断"对象已死"并回收的?
- 线上 OOM 怎么排查?
一、运行时数据区

| 区域 | 线程 | 内容 | 异常 |
|---|---|---|---|
| 堆 Heap | 共享 | 所有 new 的对象 | OutOfMemoryError: Java heap space |
| 方法区 Metaspace | 共享 | 类元数据、静态变量、常量池 | OutOfMemoryError: Metaspace |
| 虚拟机栈 | 私有 | 栈帧(局部变量、操作数栈) | StackOverflowError |
| 本地方法栈 | 私有 | native 方法 | StackOverflowError |
| 程序计数器 | 私有 | 当前字节码指令地址 | 无 |
栈存引用,堆存对象:Dog d = new Dog() —— d 引用在栈,Dog 对象在堆。GC 只管堆。
二、对象创建过程
java
Dog d = new Dog("旺财");- 类加载检查:
Dog类是否已加载。 - 分配内存:在堆(Eden 区)划一块。
- 初始化零值:字段设默认值。
- 设置对象头:Mark Word(锁/GC 标记)+ 类型指针。
- 执行构造方法:
Dog(...)初始化字段。
三、GC:判定"对象已死"
3.1 可达性分析
JVM 从 GC Roots(栈引用、静态变量、JNI 引用等)出发,能到达的对象存活,不可达的判定可回收:
| GC Roots | 说明 |
|---|---|
| 虚拟机栈引用的对象 | 局部变量、参数 |
| 静态字段引用 | static 变量 |
| 常量引用 | 字符串常量池 |
| JNI 引用 | native 方法 |
3.2 分代回收
堆按对象年龄分代,多数对象"朝生夕死":

| 分区 | 内容 | 回收 |
|---|---|---|
| 新生代 | Eden + S0 + S1(8:1:1) | Minor GC(频繁、快) |
| 老年代 | 大对象、多次存活对象 | Major/Full GC(慢) |
| Metaspace | 类元数据 | Full GC |
回收算法:新生代用复制算法(清空 Eden + 幸存者复制到另一 S);老年代用标记-清除/标记-整理。
四、常见 GC 与调优
| GC | 特点 | 适用 |
|---|---|---|
| Serial | 单线程,暂停长 | 小堆、客户端 |
| Parallel | 多线程,吞吐优先 | 后台批处理 |
| CMS | 低暂停(已废弃) | 老年代 |
| G1 | 区域化,可预测暂停 | 默认、服务端推荐 |
| ZGC/Shenandoah | 超低暂停(毫秒级) | 大堆、低延迟 |
常用调优参数:
bash
java -Xms4g -Xmx4g # 堆初始与最大
-Xmn1g # 新生代大小
-XX:+UseG1GC # 选 G1
-XX:MaxGCPauseMillis=100 # G1 目标暂停
-XX:MetaspaceSize=256m # 方法区
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/ # OOM 时导堆五、OOM 与内存泄漏排查
| 现象 | 原因 | 排查 |
|---|---|---|
Java heap space | 堆满 | 堆转储 + MAT/jmap 分析 |
Metaspace | 类加载过多(反射/动态代理) | 检查类加载器泄漏 |
unable to create new native thread | 线程数超限 | 检查线程泄漏 |
排查流程:jps 找 PID → jmap -dump:format=b 导堆 → MAT 看支配树找大对象与 GC Root 引用链。
常见泄漏源:静态集合持对象不放、未关闭的连接、Listener 未反注册、ThreadLocal 未清理。
六、与本站主线衔接
- 内存泄漏:Java 泄漏用 MAT/jmap 定位,与 C/C++ 的 Valgrind 方法不同,见 crash 内存泄漏排查。
- 对象布局:对象头、字段对齐影响内存占用,类比 L3 内存子系统 的对齐原理。
- 性能剖析:GC 停顿是 Java 性能关键指标,用
jstat -gc/Arthas 观测;见 Java 总纲。
一句话总结
JVM 内存 = 线程共享的堆/方法区 + 线程私有的栈/PC;GC 用可达性分析 + 分代回收自动管理堆,G1 是服务端默认,OOM 用堆转储 + MAT 定位;理解运行时数据区是 JVM 调优与排查的前提。
上一节:Java 核心主题总纲 下一节:并发编程与 JUC