JVM运行时数据区

程序计数器

线程私有。存储了下一条需要执行的字节码指令的地址。JVM多线程是通过线程轮换并分配执行时间的方式实现的。在任何一个确定的时间内,JVM只会执行其中一条指令。每个线程的程序计数器记录了当前执行的指令,每个线程都有自己的程序计数器,这样线程之间互不影响。如果当前线程执行的是Java方法,其程序计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是本地方法,程序计数器为空。

所有线程共享。在虚拟机启动时创建,此区域存放对象实例(包括class对象、实例对象),几乎所有的对象实例都在这里分配内存。

方法区

所有线程共享。此区域用于存放已经被虚拟机加载的类信息、常量、静态常量、即时编译器编译出来的代码等数据。

本地方法栈

线程私有。功能与虚拟机栈非常相似。来存储线程调用本地方法时,本地方法的局部变量表,操作栈等信息。

虚拟机栈

线程私有。虚拟机栈中的元素称为栈帧,线程在调用java方法时,会给每个方法都创建一个栈帧,每个方法的调用和完成的过程,都对应着一个栈帧从虚拟机栈上入栈和出栈的过程。虚拟机栈的生命周期与线程一致。

方法退出的过程实际上就等于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令等。

栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息,结构如下:

JVM中线程间的数据交换

各线程共享JVM内存中的方法区和堆:


参考资料

《深入理解Java虚拟机》,§ 2.2 运行时数据区域
《深入理解Java虚拟机》,§ 2.3 HotSpot虚拟机对象探秘
《深入理解Java虚拟机》,§ 6.3 Class类文件的结构
《深入理解Java虚拟机》,§ 7 虚拟机类加载机制
《深入理解Java虚拟机》,§ 8 虚拟机字节码执行引擎
《Java虚拟机原理图解》3、JVM运行时数据区