目录
一、线程私有
1.1 程序计数器(Program Counter)
用于存放当前线程正在或即将执行的指令地址。循环、跳转、异常处理、线程恢复等都依赖它来完成,通过修改这个值来实现流程控制。生命周期与线程一致。
1.2 虚拟机栈
虚拟机栈里面存储的是一个一个栈帧(Stack Frame),每调用一个非本地(native)方法,都会生成一个栈帧,压入虚拟机栈。虚拟机栈有最大栈深,在编译的时候已经确定,当超出最大栈深时会抛出StackOverflowError错误,栈帧在创建的时候,会分配内存,当无法申请到足够内存时,会抛出OOM错误。
1.3 栈帧的结构
栈帧主要包含:局部(本地)变量表、操作数栈、动态连接、方法返回地址等;变量表的大小和操作数栈在编译的时候可以确定。
1.3.1局部变量表
用于存储方法参数和局部变量。存储的基本单位是变量槽(slot)。存储内容包含变量的名称、类型、长度等。如果当前方法是非static修饰方法,下标为0的槽,存储着当前对象this。为了节约空间,slot也会重复利用。32位的值占用一个slot,64位的值占用2个连续的slot。
1.3.2操作数栈(Operand stack)
操作数栈主要用于计算的临时存储,存储计算的中间值。32位占用一个栈深,64位占用2个。
1.3.3动态连接
动态连接用来访问 当前方法所在类所关联常量池数据。
1.3.4方法返回地址
当方法正常执行完或遇到未处理的异常,会退出当前方法。当方法返回时,可能会恢复上个方法的局部变量表与操作数栈,如果有返回值,则把返回值压入操作数栈,调整程序计数器为下一条指令的地址。
1.4 本地方法栈
作用与虚拟机栈类似,jvm在调用native方法时,虚拟机栈不会变化,具体实现与本地方法有关。