一文看懂 JVM 内存区域分布与作用
作者:bingfeng
来源:SegmentFault 思否社区
那么我们在开始介绍Java内存区域之前,我们先放一张内存区域的图,方便我们后面介绍的时候可以对照着看。
须知,本文是根据JDK8来介绍的。
程序计数器
首先它是线程私有的,它也称为代码的行号指示器,字节码解释器就是通过改变程序计数器的位置来确定下一行要执行的代码,它不存在OOM。
如果线程正在执行一个Java方法,那么它记录的是正在执行虚拟机字节码指令的地址,如果是一个本地方法那么它的值为空。
Java 虚拟机栈
它也是线程私有的,它的声明周期和线程一致。每个线程创建时都会创建一个虚拟机栈,内部保存了一个个的栈帧,每个栈帧就对应着一次方法的调用。既然知道了虚拟机栈里面存放的是一个个的栈帧,那么也不难猜出虚拟机栈里面都存储了什么东西。
Java虚拟机栈是存在OOM的,当线程所请求的栈的深度大于虚拟机栈的深度或者虚拟机栈可以动态扩容,当栈扩展时无法申请到足够的内存时,就会抛出OOM。
虚拟机栈内部结构:
局部变量表:
主要存储方法的参数,所有的基本类型数据和对象地址,以及返回地址类型(return address)。它以变量槽为最小的存储单位,Java虚拟机并没有规定一个变量槽占用多少内存空间,但是规定了一个变量槽可以存放一个32位以内的数据类型。如果存储的数据类型超过32位,比如long、double,那么就使用两个变量槽进行存储。
操作数栈:
操作数栈是一个先进后出的操作数栈,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的,它主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。如果被调用的方法有返回值,那么返回值将会被压入当前栈帧的操作数栈中。操作数栈并非采用索引的方式进行数据访问,而是通过入栈(push)和出栈(pop)操作来完成数据的访问。
动态链接:
大白话就是,栈帧中保存了一个方法的引用,当执行方法的时候,可以拿着这个引用到运行时常量池中找到这个方法。
动态链接的作用就是将这些方法的符号引用转换为调用方法的直接引用。
方法返回地址:
就是在方法执行结束之后,要返回下一条要执行代码位置的值,也就是程序计数器的值。
那么除了方法正常执行结束退出外,还有另外一种情况就是异常导致的方法退出,那么这种情况下是不会返回任何值的。对于抛出的异常,栈帧中不会做任何记录,但是会记录在一个异常表中。