Java虚拟机内存区域划分

我们知道,Java虚拟机在Java程序运行时会将其所管理的内存划分为多个区域。这些区域各自拥有着自己的生命周期与作用,下图为《Java虚拟机规范(第二版)》所描述分布图:

Java虚拟机内存区域划分

 

一:程序计数器

程序计数器,是一块较小的内存空间,它是当前线程所执行字节码的行号指示器。不同线程之间,有着各自的计数器。彼此互不干扰,属于线程私有。此外,在本区域不会出现OutOfMemoryError,也是唯一一个不会出现该异常的区域。

二:虚拟机栈

Java虚拟机栈,也是线程私有,其生命周期与线程相同。虚拟机栈描述了Java方法执行模型,说明了Java方法执行过程中,会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等相关信息,方法执行的一个完整过程,代表着栈帧在栈中的入栈和出栈过程。在粗糙的栈和堆的分配认知里,程序员所关注的栈,其实严格意义上多数指的就是虚拟机栈中的局部变量表。局部变量表存储的是基本变量类型,对象引用类型,returnAdress类型。局部变量表所需内存空间,在编译期就是确定的。运行时不会改变。

该区域可能发生两种异常:OutOfMemoryError异常或Stack Overflow异常

三:本地方法栈

本地方法栈与虚拟机栈类似,但其服务对象为Native方法,不一样的虚拟机可能会把两者合二为一

四:Java堆

Java堆理论上是虚拟机内存最大的一块区域,其所为各个线程共享。它唯一的目的就是存放各对象实例,所以在当前的虚拟机中,几乎所有的对象都是在该区域分配。该区域在物理空间不连续,保留逻辑空间连续即可,同时,该区域可以拓展。

Java堆是作为垃圾回收的主要区域,基于不同的垃圾回收算法机制,可能该区域详细划分并不一样;这里主要说明分代收集算法的详细划分。如图是分代收集算法下的堆内存详细划分图:

Java虚拟机内存区域划分

此处我们仅做分代划分说明,垃圾回收详细,待下次说明。

五:方法区

该区域同样为各线程共享区域,主要存放装载的类信息,常量,静态变量,即时编译的字节码等信息。Java虚拟机规范对该区域保留最大的宽松要求,Java虚拟机规范将此区域描述为堆的逻辑部分,但事实上,这块区域有自己独特的性质。尽管该区域存在垃圾回收的几率小,但还是会有一部分东西被回收。在本区域,被回收的目标主要针对常量池与类型的卸载。

该区域同样可能发生OutOfMemoryError异常。

六:运行时常量池

常量池,是属于方法区的一部分,用于存放编译期生成的各种字面量与符号引用。运行时常量池具备动态性,运行时新的常量,也可以存入常量池中,可能发生OutOfMemoryError异常。

 

参考:

          周志明:《深入理解Java虚拟机(JVM高级特性与最佳实践)》