JAVA内存申请发生的阶段

张开发
2026/4/26 9:55:28 15 分钟阅读

分享文章

JAVA内存申请发生的阶段
1、Loading加载阶段 — 方法区内存.class 文件 → 加载到 JVM 方法区Metaspace / PermGen申请什么类的元数据类名、父类、接口、字段列表、方法列表方法的字节码指令常量池运行时常量池静态变量的元信息不是值本身存哪里JDK 7 及之前PermGen永久代JDK 8 及之后Metaspace元空间在本地内存中2、Preparation准备阶段 — 堆内存static 变量 → 分配内存空间 赋零值申请什么静态变量类变量的存储空间基本类型直接分配对应大小的空间引用类型分配一个引用槽位存 null存哪里堆内存具体位置取决于 JVM 实现JDK 7永久代JDK 8堆中的一个特殊区域申请什么实例对象new Object() 在堆中分配数组在堆中分配连续空间详细对照表阶段申请什么内存存储位置举例Loading类元数据、方法字节码、常量池Metaspace本地内存Class 对象Preparation静态变量的存储槽位堆static int a 分配 4 字节Initialization实例对象、数组堆new String(“hello”)运行时线程栈帧、局部变量栈方法参数、局部变量举例说明publicclassMemoryDemo{publicstaticinta100;// Preparation: 分配 4 字节赋 0publicstaticStringnamehello;// Preparation: 分配引用槽位赋 nullpublicstaticvoidmain(String[]args){MemoryDemoobjnewMemoryDemo();// Initialization/运行时: 堆中分配对象int[]arrnewint[1000];// 运行时: 堆中分配 4000 字节}}时间线1. Loading └─ MemoryDemo.class 加载到 Metaspace └─ 方法 main 的字节码存入 Metaspace └─ 常量池hello、方法引用等存入 Metaspace2. Preparation └─ static int a → 堆中分配4字节值0└─ static String name → 堆中分配引用槽位值null3. Initialization └─ a100→ 修改堆中的值为100└─ namehello→hello在字符串池name 指向它 └─ new MemoryDemo()→ 堆中分配对象内存12~16 字节对象头 实例字段4. 运行时 └─ new int[1000]→ 堆中分配4000字节 数组对象头 └─ 局部变量 obj, arr → 栈帧中分配引用槽位⚠️ 常见误区误区正确理解“Preparation 分配对象内存”❌ 只分配静态变量的槽位对象是 new 时分配“类加载就分配堆内存”❌ 类元数据在 Metaspace堆内存是对象和静态变量“static 变量在栈中”❌ static 变量在堆中栈里只有局部变量 总结图┌─────────────────────────────────────────────────────────────┐ │ JVM 内存申请时机 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Loading ──────→ Metaspace本地内存 │ │ │ ├─ 类元数据 │ │ │ ├─ 方法字节码 │ │ │ └─ 常量池 │ │ ↓ │ │ Preparation ───→ 堆内存 │ │ │ └─ static 变量槽位赋零值 │ │ ↓ │ │ Initialization → 堆内存 │ │ │ ├─ static 变量赋真实值 │ │ │ └─ 执行clinit│ │ ↓ │ │ 运行时 ────────→ 堆 栈 │ │ ├─ new 对象 → 堆 │ │ └─ 局部变量 → 栈 │ │ │ └─────────────────────────────────────────────────────────────┘一句话Loading 申请 Metaspace类元数据Preparation 申请堆内存静态变量槽位赋零值Initialization 和运行时申请堆内存对象实例

更多文章