Skip to content
极高基础

一句话答案

JVM 内存分堆(新生代/老年代)、方法区(元空间)、虚拟机栈、本地方法栈、程序计数器,其中堆和方法区线程共享。

核心要点

JVM 运行时数据区(JDK 8):

┌─────────────────────────────────────────────────────────┐
│                    JVM 运行时数据区                       │
│                                                         │
│  ┌──────────────────────────────┐  ← 线程共享            │
│  │            堆(Heap)         │                       │
│  │  Eden | S0 | S1 | 老年代      │                       │
│  └──────────────────────────────┘                       │
│                                                         │
│  ┌──────────────────────────────┐  ← 线程共享            │
│  │     方法区(Metaspace)        │                       │
│  │  类信息 | 常量池 | 静态变量     │  (JDK8 在本地内存)    │
│  └──────────────────────────────┘                       │
│                                                         │
│  ┌──────────┐  ← 线程私有                                │
│  │ 虚拟机栈  │  局部变量表、操作数栈、栈帧                  │
│  └──────────┘                                           │
│  ┌──────────┐  ← 线程私有                                │
│  │ 本地方法栈 │  Native 方法的栈帧                         │
│  └──────────┘                                           │
│  ┌──────────┐  ← 线程私有                                │
│  │ 程序计数器 │  当前线程执行的字节码行号                    │
│  └──────────┘                                           │
└─────────────────────────────────────────────────────────┘

各区域详解:

1. 堆(Heap)—— 最大的一块,GC 主战场

  • 存放:所有对象实例、数组(new 出来的东西都在这)
  • 线程共享,GC 主要回收此区域
  • 划分:年轻代(Eden + S0 + S1) + 老年代

2. 方法区(Method Area)—— JDK 8 改为 Metaspace

  • 存放:类的元信息(字段、方法、接口描述)、运行时常量池、静态变量、JIT 编译后的代码缓存
  • JDK 7 之前叫永久代(PermGen,堆内),JDK 8 改为 Metaspace(本地内存,不受 -Xmx 限制)
  • String.intern() 的字符串字面量从 JDK 7 起移入堆中

3. 虚拟机栈(VM Stack)

  • 每个线程私有,随线程创建
  • 由栈帧(Stack Frame)组成,每调用一个方法压入一个栈帧
  • 栈帧包含:局部变量表、操作数栈、动态链接、方法返回地址

4. 本地方法栈(Native Method Stack)

  • 专门服务 native 方法(JNI)
  • HotSpot 将虚拟机栈和本地方法栈合并为一个

5. 程序计数器(Program Counter Register)

  • 最小的一块内存,记录当前线程执行的字节码指令地址
  • 唯一一个不会 OOM 的区域
  • 线程切换后用于恢复执行位置
追问与易错

追问方向:

  • 方法区和元空间什么关系?(JDK8 用元空间实现方法区,存在本地内存而非堆中)
  • 虚拟机栈中存什么?(栈帧:局部变量表/操作数栈/动态链接/方法返回地址)
  • 哪些区域会 OOM?(堆/元空间/栈/直接内存都可能)

易错点:

  • ❌ "JDK8 没有方法区了"——方法区是规范概念仍存在,只是实现从永久代改为元空间
  • ❌ "栈不会溢出"——递归过深会 StackOverflowError

💡 记忆锚点

JVM内存像一栋楼:堆是公共大厅(线程共享,放对象),方法区/Metaspace是档案室(类信息),虚拟机栈是每人的办公桌(线程私有,栈帧),程序计数器是书签(记执行位置,唯一不OOM的区域)。JDK8把档案室从楼内搬到楼外(永久代变元空间,用本地内存)。