Java虚拟机运行时数据区
Java虚拟机运行时数据区主要有以下五个部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区
程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间,用于记录正在执行的虚拟机字节码指令的地址(执行java方法下),可以看作是当前线程所执行的字节码的行号指示器。程序计数器是线程私有的,每一个线程都有一个独立的程序计数器,而且各个计数器之间互不影响。这样也就保证了在进行多线程操作时,线程轮流切换后能够恢复到正确的执行位置。
如果正在执行的是Native方法,则计数器的值为空。此内存区域是唯一一个在JVM规范中没有规定OutOfMemoryError情况的区域。
Java虚拟机栈
与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程同步。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表、方法返回以及操作数栈等。局部变量表中存放了各种基本数据类型、对象引用和指向一条字节码指令的地址。每一个方法的调用到执行完成,都对应一个栈帧在虚拟机栈中从入栈到出栈的过程。局部变量表的内存空间在编译器完成分配,即当进入一个方法时,该方法在桢中所需的局部变量空间是完全确定的,在方法运行期间不会改变其大小。
JVM中该区域存在的异常状况:
1.如果线程请求的栈深度大于虚拟机允许的深度,则抛出StackOverflowError异常。
2.如果虚拟机栈可以动态扩展,当扩展无法申请到足够的内存,抛出OutOfMemoryError异常。
本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用类似,它们之间的区别是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的netive方法服务。
同样会抛出StackOverflowError和OutOfMemoryError异常。
Java堆
Java堆(Java Heap)是JVM中内存占用最大的区域。是被所有线程共享的,在虚拟机启动时创建。所有的对象实例和数组都要在堆中分配,同时Java堆是垃圾收集器管理的主要区域(当对象实例不再被引用时,就需要被销毁,让出多余的内存空间)。
如果堆中没有足够的内存完成实例分配,而且堆也无法在进行扩展,将会抛出OutOfMemoryError异常。
方法区
方法区(Method Area)也是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息,常量,静态变量等。该区域的内存回收主要的针对常量池和加载过的类信息的回收,然而由于类信息的卸载要求相当苛刻,会发生未完全回收而导致内存泄漏的情况。
如果方法区无法满足内存分配需求,将抛出OutOfMemoryError异常。
运行时常量池
运行时常量是方法区的一部分,用于存放编译期生成的字面量和符号引用,在运行期间也可以将新的常量放入池中。1
《深入理解JVM虚拟机》 ↩︎