Chris's Blog

Keep Walking......

JVM运行时内存区域

Java虚拟机管理的运行时数据区域:

  • 程序计数器

    是当前线程所执行的字节码的行号指示器。每条线程都有一个独立的程序计数器,各线程之间的计数器互不影响,该内存区域为线程私有,也不会出现OutOfMemoryError。

  • Java虚拟机栈

    该区域也是线程私有,其生命周期与线程相同。虚拟机栈表述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

    局部变量表存放了编译期可知的基本类型、对象引用(可能是一个指向对象起始地址的指针,也可能是指向一个对象的句柄,或者是与此对象相关的位置)和retuanAddress类型。64位长度的long和double类型占用2个局部变量空间,其余类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,方法运行期间不会改变。

    在本区域中,若线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError;若动态扩展无法申请到足够的内存时抛出OutOfMemoryError。

  • 本地方法栈

    与虚拟机栈的作用相似,区别是虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用到的Native方法服务。有的虚拟机实现会将虚拟机栈和本地方法栈合在一起。

  • Java堆

    可被所有线程共享,在虚拟机启动时创建。此区域只用于存放对象实例,是垃圾收集器管理的主要区域。堆的扩展可通过-Xmx和-Xms控制。若堆中没有内存完成实例分配,也无法扩展时,将抛出OutOfMemoryError。

  • 方法区

    可被所有线程共享,用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虚拟机规范将方法区描述为堆的一个逻辑部分。该区域很少进行垃圾回收的操作。

    若方法区无法满足内存分配需求时,将抛出OutOfMemoryError。

对象访问方式

虚拟机规范中未定义对象访问的方式,在主要的虚拟机实现中包含如下两种方式:

  • 句柄访问

    在Java堆中划分出一块内存作为句柄池,Java栈中对象引用存储的就是对象的句柄地址,句柄中包含了对象实例数据和类型数据的地址信息。

    这种方式在对象引用中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,对象引用本身不需要被修改。

  • 指针访问

    Java栈中对象引用存储的就是对象的地址。这种方法的访问速度更快,节省了一次指针定位的开销。

Comments