JVM Run-Time Data Areas

对于C++来说,程序员是内存的管理者,他拥有每一个对象的所有权,担负着该对象生命从创建到终结的整个过程(new->delete 成对匹配)。
而Java程序员来说,内存的管理工作由虚拟机承担,Java程序员仅仅是内存的使用者。由JVM来自动进行内存管理极大的方便了用户的使用,使其不容易出现内存泄露或者是溢出的问题,与此同时,一旦出现内存泄露或溢出,我们将很难查错。因此,了解JVM的内存管理机制是Java程序员必需的一项工作。

Run-Time Data Areas

JVM定义了各种不同的运行时数据区供程序运行时使用。它们有的随JVM的启动而创建,随JVM的退出而销毁,其他的一些是线程所有的,随线程的创建而创建,随线程的退出而销毁。

JVM Run-Time Data Areas_第1张图片

  1. The Programming-Counter Register 程序计数器
    JVM支持多线程工作,工作模式是处理器时分复用,为了在线程切换后使其能够正确恢复,JVM为每个线程都分配了一个PC计数器,各个线程之间的计数器互不影响,独立存储。我们称之为 “线程私有" 的。
    当当前正在执行的方法 is not native, PC的值是其下一条指令的地址,若当前方法 is native ,PC register is undefined 。
    此内存区JVM中唯一一个没有OutOfMemoryError的情况。

  2. Java Virtual Machine Stacks Java虚拟机栈
    同PC计数器一样,Java Virtual Machine stacks 是线程私有的,随线程的创建而创建。
    Java虚拟机栈是以帧(frame)的方式组建的。当一个方法被调用时会创建一个新的栈帧,该方法调用结束时对应的栈帧也随之销毁(不管该方法是正常退出还是非正常的)。
    栈栈中存放了类中当前方法的局部变量表、操作栈、动态链接和方法出口等信息。
    JVM Run-Time Data Areas_第2张图片
    1)Local Variables(Local Variable Array )局部变量表
    局部变量表的大小在编译期就确定了,它可以存储包括boolean, char, byte, short, int, double , float, double, reference(指向了堆对象的地址) 和 returnAddress类型(指向了一条字节码指令地址)的值,其中,long 和 double 型数据占用了连续的两个局部变量空间(未知大小),其余数据类型只占用一个。因此,局部变量表的大小仅取决于JVM的实现。
    局部变量表通过索引(index)进行访问,索引 的取值范围为 [ 0,array.length ) 。
    2)Operand Stacks

    Java虚拟机规范中对这个区域规定了两种异常情况:
    StackOverflowError,当线程请求超过JVM Stacks所允许的深度时, JVM throws a StackOverflowError 。
    OutOfMemoryError,若JVM Stacks可以动态扩展(事实上,当前大部分的Java虚拟机都可动态扩展),当内存无法满足其扩展请求即无法申请到足够的内存时,JVM throws an OutOfMemoryError。

  3. Native Method Stacks
    顾名思义,本地方法栈就是为 Native Methods 服务的,它的功能同虚拟机栈非常相似。
    Native Methods 就是用非Java语言写的方法,可以被 JVM 调用。
    同虚拟机栈一样,本地方法栈也可以是固定大小或动态扩展的,也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

  4. Heap
    堆是线程共享的,它随着虚拟机的启动而创建,是用来存放对象和数组一块区域。
    在Java语言中,对象不是准确删除的(delete),而是通过 Garbage Collector 也就是自动内存管理系统进行管理的,垃圾回收器也主要就是为堆区进行服务。
    堆可以是固定大小或根据计算需求动态扩展,当需求大于堆能够提供的最大情况时会抛出OutOfMemoryError异常。
    堆内存在物理上不要求连续的存储空间。

  5. Method Area
    方法区是线程共享的,它存储类的相关信息,包括运行时常量池、字段和方法数据,方法和构造函数代码等
    方法区在逻辑上是堆区域的一部分,可以是固定大小或或者动态扩展,物理内存区域不要求连续。 与堆不同的是,方法区的垃圾回收行为较少,甚至可以选择不进行垃圾回收。
    当方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。

  6. Run-Time Constant Pool
    运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将会在类加载后存放在运行时常量池中。
    和方法区一样,当常量池无法在申请到内存时,抛出OutOfMemoryError异常。

你可能感兴趣的:(JVM内存管理,运行时数据区,JVM规范)