JVM 把进程内存划分为若干区域:堆放对象、虚拟机栈放方法栈帧、方法区放类元数据、程序计数器记当前指令。理解这块是排查 OOM、StackOverflow、GC 的前提。这一页把五个区域的职责、线程共享与否、存什么讲透。
别急着背代码,先按这四步建立直觉:
虚拟机栈(线程私有):每调一个方法就压一个栈帧,里面放局部变量表、操作数栈、返回地址。方法返回栈帧弹出。递归太深栈帧太多就 StackOverflowError。
堆(线程共享):new 出来的对象都在堆里,是 GC 主战场。堆满了又回收不掉就 OutOfMemoryError: Java heap space。
方法区(共享):存类的元信息、常量池、静态变量。JDK8 后用本地内存的元空间 Metaspace实现。
程序计数器(私有):记当前线程执行到哪条字节码,唯一个不会 OOM 的区域。
Object o = new Object();:引用 o 在栈帧局部变量表,真正的 Object 对象在堆。栈里存的只是地址指针。| 区域 | 线程共享 | 存什么 | 溢出异常 |
|---|---|---|---|
| 程序计数器 | 私有 | 当前字节码行号 | 无 OOM |
| 虚拟机栈 | 私有 | 栈帧:局部变量、操作数栈 | StackOverflowError / OOM |
| 本地方法栈 | 私有 | native 方法 | 同上 |
| 堆 | 共享 | 对象实例、数组 | OOM: Java heap space |
| 方法区/元空间 | 共享 | 类元数据、常量、静态变量 | OOM: Metaspace |
| 参数 | 作用 |
|---|---|
| -Xms | 堆初始大小 |
| -Xmx | 堆最大大小 |
| -Xss | 每个线程栈大小(默认 512K~1M) |
| -XX:MetaspaceSize | 元空间初始上限 |
| 考法 | 出题形式 | 应对 |
|---|---|---|
| 五块区域 | 问存什么/谁共享 | 背总表 |
| 异常定位 | 抛啥异常对应哪块 | 栈 SOE,堆 OOM |
| 对象位置 | new 的对象在哪 | 堆 |
| JDK8 变化 | 永久代换成什么 | 元空间 |
真题基础1. new 出来的对象实例主要分配在?
真题中档2. 递归调用过深会抛出?
真题中档3. JDK8 后方法区由什么实现?
真题拔高4. 下列哪个区域是线程私有的?
| 天 | 任务 | 自检 |
|---|---|---|
| 第 1 天 | 读②③④,画五区图 | 谁私有谁共享对 |
| 第 2 天 | 背总表 + 基础 1-6 | 异常对应对 |
| 第 3 天 | 做中档 7-12,定位对象位置 | 栈/堆分清 |
| 第 4 天 | 做拔高 13-18,理解逃逸分析 | 能讲清栈上分配 |
| 第 5 天 | 做⑦真题 4 题 | 限时每题 2 分钟 |
| 第 6-7 天 | 合上书默写五区表 | 不看资料全默对 |