运行时数据区包括:方法区、堆、虚拟机栈、本地方法栈、程序计数器。其中前两个是线程共享的,后面三个是线程私有的。

1.方法区:

类的名称、方法信息、字段信息)、常量、静态变量、JIT编译后的代码。是线程共享的,

        方法区里有一个部分叫常量池,编译期生成的各种字面量和符号引用会在类加载后进入方法区的运行时常量池中。在厂商的实现中,常量池里通常还会存放翻译出来的直接引用。

        常量池存放的内容不是固定的,在运行期间可能将新的常量放入池中。

    如果方法区的内存不够分配,会抛出OutOfMemeryError异常。

2.堆

    堆用于存放对象实例,是JVM的内存里最大的部分,是线程共享的,在JVM启动时创建。在规范中,所有的对象和数组都要在堆上分配,不过在实践中不那么绝对。

    堆的物理内存可以是不连续的,只需要逻辑上连续,一般实现为可扩展的。当堆中内存不足以完成分配,且无法扩展,会抛出OutOfMemeryError异常。

3.虚拟机栈

    虚拟机栈用于描述Java方法的执行。是线程私有的。可以动态扩展。

    每个方法在执行时都会创建一个栈帧,存储了局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

    局部变量表:存放编译期可以确定的基本数据类型(String不是基本类型)、对象引用、returnAddress类型。所需的空间在编译期间完成分配,在方法运行期间,空间大小不会改变。

    如果线程请求的栈深度大于虚拟机的限制,会抛出StackOverflowError异常;如果扩展时申请不到足够的内存,会抛出OutOfMemeryError异常。

4.本地方法栈

    类似虚拟机栈,区别是本地方法栈用于虚拟机使用的Native方法。HotSpot虚拟机把它和虚拟机栈合并。

    和虚拟机栈一样,StackOverflowError和OutOfMemeryError异常。

5.程序计数器

    就当是CPU里的PC。给Java方法用的。线程私有。

    执行Native方法是计数器是空的。