JVM内存结构是什么?分别用来存储什么数据?代码举例讲解

JVM内存主要由以下几个运行时数据区域组成:

  • 堆(Heap):用于存储对象实例,由GC管理。
  • 方法区(Method Area):用于存储类信息、常量、静态变量等,由JVM垃圾回收器管理。
  • 虚拟机栈(VM Stack):用于存储栈帧,由JVM自管理。
  • 本地方法栈(Native Method Stack):用于与操作系统交互的方法,由操作系统管理。
  • 程序计数器(PC Register):用于记录当前线程所执行的字节码行号,由JVM自管理。

堆和方法区在JVM启动时创建,一直持续到JVM退出。栈和本地方法栈是为每个线程创建的,程序计数器也是每个线程独立维护的。

来看一个简单例子:
我们可以编写一个Java程序,然后使用 VisualVM工具查看其对应的JVM内存区域。

  1. 编写一个简单的Java程序:
public class Sample {
    public static void main(String[] args) {
       method1();
        method2();
    }

    public static void method1() {
        int a = 10; // 存储在虚拟机栈  
        String b = "Hello"; // 存储在堆  
        final double c = 3.14; // 存储在方法区 
    }  

    public static void method2() {
        long d = 100L; // 存储在虚拟机栈
        char e = 'a'; // 存储在方法区
    }
}
  1. 启动VisualVM,通过”VisualVM > Add JMX Connection”连接此Java程序进程。
  2. 在VisualVM界面可以看到对应的各内存区域的内存使用情况:
    • 堆:可以观察对象”Hello”的大小和地址等信息。
    • 方法区:可以观察字符串常量”Hello”、final常量3.14的大小和地址信息。
    • 虚拟机栈:可以观察栈帧中的基本变量a、d的大小,但是无法看到具体的值。这是因为虚拟机栈的数据是线程私有的。

从这个简单示例可以直观地观察到不同数据会存储在JVM的哪些内存区域。