Java内存区域——运行时数据区域

来源:互联网 发布:西餐锅具 知乎 编辑:程序博客网 时间:2024/05/06 09:07

2016-07-15

1、运行时数据区域

    Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。根据《Java虚拟机规范(JavaSE 7 版本)》的规定,Java虚拟机所管理的内存的运行时数据区域包括两类:所有线程共享的数据区和线程隔离的数据区。

    其中,线程共享的数据区包括:方法区(Method Area)和堆(Heap)。而,线程隔离的数据区包括:虚拟机栈(VM Stack),本地方法栈(NativeMethod Stack)和程序计数器(Program Counter Register)。

1.1   程序计数器

    程序计数器是一块内存较小的空间,它可以看做是当前线程所执行的字节码的行号指示器。计数器可以决定下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程回复等基础功能都需要依赖这个计数器来完成。

    如果线程正在执行的是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址;如果线程执行的是Native方法,计数器值为空。

1.2   Java虚拟机栈

    虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就是一个栈帧在虚拟机中入栈到出栈的过程。

    局部变量表存放了编译期可知的各种基本数据类型(Boolean,byte,char,short,int,float,double)、对象引用和returnAddress类型。

    Java虚拟机规范中,对Java虚拟机栈规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机可以动态扩展,且扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

1.3   本地方法栈

    本地方法栈和Java虚拟机栈发挥的作用相似。区别在于:虚拟机栈为虚拟机执行Java方法提供服务,而本地方法栈则为虚拟机使用到Native方法服务。与Java虚拟机一样也会抛出StackOverflowError异常和OutOfMemoryError异常。

1.4   Java堆

    目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。(补充:在Java虚拟机规范中提到:所有的对象实例以及数组都要在堆上分配内存。除逃逸分析和标量替换之外。后序会涉及到这两种情况)

    Java堆,既可以固定大小,也可是可扩展的。可以处于物理上不连续的内存空间中,只要逻辑上连续的即可。如果在对重中没有完成实例分配,并且堆也无法在扩展时,将会抛出OutOfMemoryError异常。

1.5   方法区

    方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、及时编译器编译后的代码数据。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

2         运行时常量池

    运行时常量池是方法区的一部分。主要特点:1)每一个字节用于存储哪种数据没有规定,提供商根据自己的需求来实现内存区域。2)具备动态性。既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。

 

    注:直接内存也可能导致OutOfMemoryError异常,但是,它不属于运行时数据区域。
0 0