首页 > 代码库 > Java虚拟机运行时数据区结构

Java虚拟机运行时数据区结构

本文部分参考自《Java虚拟机规范(Java SE 7版)》的中译本和周志明的《深入理解Java虚拟机》,另加个人理解。原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所限,不排除存在认知错误。

JVM将程序运行期间使用的内存划分为若干个运行时数据区,其中一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些与线程一一对应,随着线程开始而创建,随着线程结束而销毁。数据区划分如下图所示意:

Java堆(Java Heap)

在JVM中,Java堆是可供各个线程共享的运行时内存区域,是供所有类实例和数组对象分配内存的区域。Java堆在虚拟机启动时被创建,存储了垃圾收集器(GC)管理的各种对象,这些对象无法显式销毁。

Java堆可能发生OutOfMemoryError错误。

方法区(Method Area)

方法区用于存储已被虚拟机加载的类的结构信息,例如:运行时常量池、字段和方法数据、构造函数和普通方法的字节码,还包括一些在类、实例、接口初始化时用到的特殊方法。

方法区逻辑上是Java堆的一部分,但JVM规范对方法区限制非常宽松,可以选择不实现垃圾收集。实际因为类型卸载的条件非常苛刻,方法区的垃圾收集效果也不理想。

方法区可能发生OutOfMemoryError错误。

运行时常量池(Runtime Constant Pool)

每个类或接口的字节码中去了有类的版本、字段、方法、接口等描述信息外,还包含一个常量池表(constant_pool table),用于存放编译期生成的各种字面值和符号引用,运行时常量池是这个常量池表的运行时表示形式。每个运行时常量池都在JVM的方法区中分配,在加载类和接口到虚拟机后,就创建对应的运行时常量池。

在创建运行时常量池时,JVM可能会抛出OutOfMemoryError错误。



PC计数器(Program Counter Register)

JVM线程私有,保存当前线程正在执行的字节码指令的地址,如果正在执行的是Native方法,值为undefined,本内存区域没有规定内存错误。

Java虚拟机栈(Java Virtual Machine Stack)

在第一版中也称为Java Stack,每一条JVM线程都有自己私有的Java虚拟机栈,这个栈与线程同时创建,用于存储栈帧(Frame)。

Java虚拟机栈可能发生StackOverFlowError和OutOfMemoryError错误。

本地方法栈(Native Method Stack)

JVM线程私有,和Java虚拟机栈作用类似,Java虚拟机栈为虚拟机执行Java方法服务,而本地方法栈为虚拟机执行Native方法服务。JVM规范没有规定本区域如何实现,Sun HotSpot虚拟机直接把本地方法栈和Java虚拟机栈合成了一个。和Java虚拟机栈一样,本地方法栈也可能抛出StackOverFlowError和OutOfMemoryError错误。

栈帧(Stack Frame)


栈帧是用于存储数据和部分过程结果的数据结构,每次方法调用对应一个栈帧,随着方法调用而创建,随着方法结束而销毁。栈帧的空间分配在Java虚拟机栈中,每个栈帧包括自己的本地变量表、操作数栈和动态链接(指向当前方法所属类的运行时常量池的引用)。



Java虚拟机运行时数据区结构