Jvm内存模型-实际运行对应

131 阅读3分钟

JVM 内存模型与运行时数据存储对应关系

内存区域存储内容生命周期线程隔离性GC 管理
堆 (Heap)所有通过 new 创建的对象实例 数组对象 字符串常量池(JDK7+)对象存活到被 GC 回收线程共享是(主要回收区域)
虚拟机栈 (JVM Stack)方法调用的栈帧: - 局部变量(基本类型、对象引用) - 方法参数 - 操作数栈随方法调用创建,方法结束销毁线程私有(每个线程独立)
方法区 (Method Area)类元信息(Class 结构) 运行时常量池(字符串字面量、符号引用) 静态变量(static)类加载时分配,卸载时回收线程共享是(JDK8+ 由元空间管理)
程序计数器 (PC Register)当前线程执行的字节码指令地址线程生命周期内存在线程私有
本地方法栈 (Native Stack)Native 方法(C/C++ 实现)的调用信息随本地方法调用创建,结束销毁线程私有

各区域详细说明与代码示例

1. 堆 (Heap)

  • 存储内容:所有对象实例和数组。

  • 示例

    Object obj = new Object();  // obj 引用在栈,对象本体在堆
    int[] arr = new int[10];    // 数组对象存储在堆
    String s = "Hello";         // 字符串常量存储在堆的字符串常量池(JDK7+)
    
  • 特点

    • 通过 -Xmx 和 -Xms 参数配置大小。
    • 分为新生代(Eden + Survivor)和老年代。

2. 虚拟机栈 (JVM Stack)

  • 存储内容:方法调用的局部变量和方法操作栈。

  • 示例

    public void method() {
        int a = 10;             // 基本类型变量 a 存储在栈
        String str = "World";   // 对象引用 str 存储在栈,对象本体在堆
        Object obj = new Object(); // 引用在栈,对象在堆
    }
    
  • 特点

    • 每个方法对应一个栈帧。
    • 栈溢出会抛出 StackOverflowError

3. 方法区 (Method Area)

  • 存储内容:类结构、常量池、静态变量。

  • 示例

    public class MyClass {
        static int count = 0;    // 静态变量存储在方法区
        final String NAME = "JVM"; // 常量 NAME 存储在运行时常量池(方法区)
    }
    
  • 特点

    • JDK8 之前称为“永久代”,JDK8+ 改为“元空间”(Metaspace),使用本地内存。
    • 溢出会抛出 OutOfMemoryError: Metaspace

4. 程序计数器 (PC Register)

  • 存储内容:当前线程执行的字节码指令地址。

  • 示例

    public void loop() {
        for (int i = 0; i < 10; i++) { 
            // 程序计数器记录当前循环执行位置
        }
    }
    
  • 特点

    • 唯一不会发生 OutOfMemoryError 的区域。
    • 多线程切换时用于恢复执行位置。

5. 本地方法栈 (Native Stack)

  • 存储内容:Native 方法(如 JNI 调用)的执行信息。

  • 示例

    public native void nativeMethod();  // 调用本地方法时使用此栈
    
  • 特点

    • 与虚拟机栈类似,但服务于 Native 方法。
    • 由 C/C++ 实现的方法调用链。

内存交互关系图示

+-------------------+     +-------------------+
|  虚拟机栈 (Stack)   |     |     堆 (Heap)      |
| - 局部变量         |<----| - 对象实例        |
| - 对象引用         |     | - 数组           |
+-------------------+     +-------------------+
           |
           v
+-------------------+
| 方法区 (Method Area)|
| - 类元信息         |
| - 运行时常量池     |
| - 静态变量         |
+-------------------+

总结规则

  1. 对象本体在堆:所有 new 操作创建的对象实体。
  2. 引用在栈:对象引用、方法参数、局部变量存储在栈。
  3. 类元信息在方法区:类的结构、静态变量、常量池信息。
  4. 线程私有区域:栈、程序计数器、本地方法栈为线程私有,堆和方法区为线程共享。