1.程序计数器
概念
程序计数器也叫作 PC 寄存器,是一块很小的内存区域,可以看做是当前线程执行的字节码的行号指示器。字节码的解释工作就是通过改变程序计数器里面的值来获得下一条需要执行字节码的指令。
特点
-
Pc 寄存器表现为一块内存,功能是存放伪指令,确切的说是存放的将要执行指令的地址。
-
当虚拟机正在执行的是一个 native 方法时,JVM 的 PC 寄存器存储的值是 undefined。
-
程序计数器是线程私有的,它的生命周期和线程一样,每个线程只有一个。这也是为了保证多线程下,线程切换后能恢复到正确的执行位置,所以每个线程需要独立的程序计数器,相互隔离互不影响。
-
此区域是唯一一个没有 OOM 情况的区域。
图例
2.虚拟机栈
概念
JAVA 虚拟机栈的生命周期和线程相同,他也是线程私有的,每一个线程有自己独立的虚拟机栈。他用来存储栈帧,程序运行时,每一个方法被调用执行时都会创建一个栈帧,用来存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
图例演示
栈帧
栈帧是支持虚拟机方法调用和执行的数据结构。栈帧中存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。每一个方法的调用和执行完成都对应着一个栈帧从虚拟机栈中入栈到出栈的过程。
设置虚拟机栈的大小
-Xss 为 JVM 启动时的每个线程分配的内存大小,也就是可以设置线程栈的大小。
-Xss1m # 单位为MB
-Xss1024k #单位为KB
-Xss1048576 #字节大小
复制代码
局部变量表
局部变量表是一组变量值存储空间,用于存放方法的参数和方法内定义的局部变量。
操作数栈
操作数栈是一个后入先出栈(LIFO)。随着方法执行和字节码指令的执行,会从局部变量表或者对象实例的字段中复制常量或者变量写到操作数栈,再随着计算的进行会将栈中的元素出栈到局部变量表或者返回给方法调用者。
动态链接
java 虚拟机中,每一个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的为了支持方法调用过程中的动态链接。 动态链接的作用:将符号引用转换为直接引用。
方法返回地址
方法返回地址存放调用该方法的 PC 寄存器的值。一个方法的结束,有两种方式:正常地执行完成,出现未处理的异常非正常的退出。无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的 PC 计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。无论方法是否正常完成,都需要返回到方法被调用的位置,程序才能继续进行。