4.java内存区域和内存溢出

java运行时数据区域分为以下几种:

4.java内存区域和内存溢出_第1张图片

1.程序计数器

      1.1简介

      程序计数器是一块较小的内存区域,是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型中,字节码解释器工作时就是通过改变这个计数器的值来选取下一跳需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个行号指示器。想一想我们平时debug时的一行行的debug模式,非常相像。

      多线程模式下,在一个确定的时刻,一个处理器只会执行一条线程中的指令。为了线程切换后能恢复到正确的执行位置,那么每条线程度需要有一个独立的计数器,各个线程互不影响,独立存储,所以我们称之为线程私有的内存。

      1.2 内存溢出

      如果线程执行的是一个java方法,这个计数器记录的是正在执行的虚拟机的字节码指令地址;如果执行的是native方法,那么这个计数器为undefined.这个区域,不会出现OutOfMemoryError的情况。

 

2.java虚拟机栈

      1.1简介

         跟程序计数器差不多,java虚拟机栈也是线程私有,他的生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型。每个方法在执行的同时都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用到执行完成的过程,就是一个栈帧在虚拟机栈中入栈到出栈的过程。

         局部变量表

          局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。局部变量表的容量以变量槽(Variable Slot)为最小单位,Java虚拟机规范并没有定义一个槽所应该占用内存空间的大小,但是规定了一个槽应该可以存放一个32位以内的数据类型。在Java程序编译为Class文件时,就在方法的Code属性中的max_locals数据项中确定了该方法所需分配的局部变量表的最大容量。(最大Slot数量)

         一个局部变量可以保存一个类型为boolean、byte、char、short、int、float、reference和returnAddress类型的数据。reference类型表示对一个对象实例的引用。returnAddress类型是为jsr、jsr_w和ret指令服务的,目前已经很少使用了。虚拟机通过索引定位的方法查找相应的局部变量,索引的范围是从0~局部变量表最大容量。如果Slot是32位的,则遇到一个64位数据类型的变量(如long或double型),则会连续使用两个连续的Slot来存储。

         

        操作数栈

      操作数栈(Operand Stack)也常称为操作栈,它是一个后入先出栈(LIFO)。同局部变量表一样,操作数栈的最大深度也在编译的时候写入到方法的Code属性的max_stacks数据项中。

      操作数栈的每一个元素可以是任意Java数据类型,32位的数据类型占一个栈容量,64位的数据类型占2个栈容量,且在方法执行的任意时刻,操作数栈的深度都不会超过max_stacks中设置的最大值。

      当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。

 

你可能感兴趣的:(4.java内存区域和内存溢出)