JVM运行时数据区域(Java Virtual Machine Run-Time Data Areas)

Java虚拟机在运行程序期间会划分运行时数据区域,有些数据区域随着jvm的启动而创建,退出而销毁。有些数据区域随着线程的启动和结束而创建和销毁。

这里放一张我盗来的图,图来源文章链接在文末;

Java中item代表什么 java meta_JVM


从上图可以看出来、PC Register、JVM Stack、Native Method Stack 是线程私有的数据区域,而Heap ,Method Area是共有的数据区域。下面我们来详细了解下各个数据区域。

PC(Program Counter) Register 程序计数寄存器

在深入理解Java虚拟机一书中,pc register翻译为程序计数器;个人翻译为程序计数寄存器 (我喜欢,任性)。
jvm可以支持多个线程并发执行,每个线程都有自己独立的pc register,在某一时刻,某个java线程正在执行的某个方法,如果这个方法是native方法,计数器的值为空(undefined),如果这个方法不是native方法,计数器的值为正在执行的虚拟机字节码指令的地址。

JVM Stacks Java虚拟机栈

从图中可以看出,每个线程都有自己独立的栈,随着线程的创建而创建,结束而销毁。

一个栈中存储了帧(frames),帧里面存了局部变量表、操作数栈、动态链接、方法出口等信息。

下面是我盗来的另一张图,很形象的描述了栈和帧的关系。(文末放传送门)

Java中item代表什么 java meta_数据区_02


在这个区域,有两种异常状况:

  • StackOverflowError
    如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出该异常。
  • OutOfMemoryError
    如果虚拟机栈可以动态扩展(当前大部分JVM都可以动态扩展),如果扩展时无法申请到足够的内存,将会抛出该异常.

Native Method Stacks 本地方法栈

本地方法栈与虚拟机栈作用类似,他们的区别不过是,虚拟机栈为Java方法服务,而本地方法栈为native方法服务,与虚拟机栈一样,本地方法栈也会抛出StackOverflowError与OutOfMemoryError 异常。

Heap 堆

看最上面那个图就知道,Heap是被所有线程所共享的一块数据区域。该数据区域随着JVM启动时而创建,该数据区域存储了所有的对象(Class Instance)和数组。Heap是垃圾收集器管理的主要区域,所以别名GC堆(Garbage Collector Heap(叫垃圾堆好像也没啥毛病))。
根据Java 虚拟机规范的规定,Java Heap 可以处在物理上不连续的内存空间中,只要逻辑上是连续的即可。
该区域可能抛出异常:

  • OutOfMemoryError.
    当堆中内存不足以分配给新创建的对象时,就会抛出该异常.

Method Area 方法区 (别名Non-Heap 非堆)

和堆一样,方法区也是被所有线程所共享的内存区域,方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
该区域可能抛出异常:

  • OutOfMemoryError.
    当堆中内存不足以分配给新创建的对象时,就会抛出该异常.

Run-Time Constant Pool 运行时常量池

运行时常量池是每个类或每个接口运行时类文件中的constant_pool表的表现形式。
每个运行时常量池由JVM方法区分配内存。
该区域可能抛出异常:

  • OutOfMemoryError.
    When creating a class or interface, if the construction of the run-time constant pool requires more memory than can be made available in the method area of the Java Virtual Machine, the Java Virtual Machine throws an OutOfMemoryError.

参考资料