栈帧数据说明
2019-04-25 22:27:05 0 举报
描述操作数栈中的栈帧数据结构, 理解栈帧在方法执行过程中的大致作用
作者其他创作
大纲/内容
局部变量表
布局变量表
代码片段
虚拟机执行引擎
slot4
。。。。。。
slot1
...... ......
test操作数栈
...... ......
返回地址
栈帧n-1
局部变量...
说明:如果是正常退出,都是执行xreturn字节码,xreturn会把当前操作数栈顶的数据压入到调用者栈帧的操作数栈中。源码分析:这里代码可能会出现如下异常:1.try中出现异常,被catch捕获。2.try中出现异常,没有被catch捕获。3.catch中出现异常。4.finally中出现异常。所有这里的Exception table(异常表)会有4条记录。athrow会将没有捕获到的异常抛出,此时为异常退出。
代码片段3
局部变量
slot2
代码片段2
this(这里是S的实例引用)
问题1:局部变量表与gc
执行引擎:即执行编译好的字节码指令。执行字节码是有两种方式:解释执行与编译执行。这里会说明执行引擎是如何执行字节码的。注:阐述的内容都是概念模型,不同的JVM厂家实现可能存在差异。
int1
重叠区域
操作数栈
问题2:局部变量的初始化
方法返回地址
int2
bytes变量是否能够被gc掉的根本原因是:局部变量是GC Roots的一部分,局部变量表的中的Slot是否还存在对bytes变量的引用,决定了bytes变量是否能够被回收。代码片段的解释 >代码片段1:这个很明显,整个main方法都是bytes的作用域,Slot一直存在对bytes变量的引用。代码片段2:当调用System.gc()时,确实离开了bytes变量的作用域,但Slot中任然存在对bytes变量的引用。span style=\"font-size: inherit;\
栈帧n
方法参数
say局部变量表
虚拟机栈
当前栈帧
栈帧1
栈帧2
虚拟机概念模型中每二个栈帧都是相互独立的,但在实际应用是我们知道一个方法调用另一个方法时,往往存在参数传递,具体的做法是把要传递的参数值压到操作数栈中,然后调用调用其他方法时,从操作数栈中拷贝值。这种做法在虚拟机实现过程中会做一些优化,具体做法如下:令两个栈帧出现一部分重叠。让下面栈帧的一部分操作数栈与上面栈帧的部分局部变量表重叠在一起,方法调用时就不用从操作数栈中拷贝值了。java虚拟机的解释执行引擎称为\"基于栈的执行引擎\",其中所指的\"栈\"就是操作数栈。
虚拟机规范允许实现虚拟机时增加一些额外信息,例如与调试相关的信息。一般把把 动态连接、方法返回地址、其他额外信息归成一类,称为栈帧信息。
数据重叠优化
动态连接
this(这里是A的实例引用)
slot0
两个有趣的问题
附加信息
方法调用时
方法退出时会做的操作:恢复上次方法的局部变量表、操作数栈,把当前方法的返回值,压入调用者栈帧的操作数栈中,使用当前栈帧保存的返回地址调整PC计数器的值,当前栈帧出栈,随后,执行PC计数器指向的指令。
分析栈帧
实例
字节码的执行过程也可以看成方法的执行过程,虚拟机栈是用来支持虚拟机执行引擎进行方法调用和方法执行基础。虚拟机栈有栈帧构成,方法的调用过程对应着栈帧在虚拟机栈中的入栈与出栈过程。栈帧:局部变量表+操作数栈+动态链接+返回地址+额外信息注意:栈帧中的数据在编译后就已经确定了,写在了字节码文件的code属性中。当前栈帧有效:一个线程的方法调用链可能会很长,这意味着虚拟机栈会被压入很多栈帧,但在线程执行的某个时间点只有位于栈顶的栈帧才是有效的,该栈帧称为“当前栈帧”,与这个栈帧相关联的方法称为“当前方法”。
a
方法退出方式有:正常退出与异常退出理论上,执行完当前栈帧的方法,需要返回到当前方法被调用的位置,所以栈帧需要记录一些信息,用来恢复上层方法的执行状态。正常退出,上层方法的PC计数器可以做为当前方法的返回地址,被保存在当前栈帧中。\
不知道大家有没有注意到,类变量、对象属性、参数列表中的变量 都不会报与代码片段类似的错,即使我们的代码中没有显式的初始化。这是因为在java中没有赋初值的变量是不能被使用的。也就是说类变量、对象属性、参数列表中的变量都是存在默认的初始化的。类变量:在类加载的\"准备阶段\"存在类变量的初始化。(注:类加载将会在另一个processon文件中说明)对象属性:在对象的创建过程中,当对象内存分配完成后,虚拟机将分配到的内存空间都初始化为0,即原始类型赋值为0,对象赋值为null(注:对象的创建过程可以在https://www.processon.com/view/link/5c8fc1f9e4b0afc7441681a6中查看)参数列表:当方法被调用的时候,会用调用时填写的实参值,初始化形参的值。
源码:public class ExploreReturn { public int inc() { int x; try { x = 1; return x; } catch (Exception e) { x = 2; return x; } finally { x = 3; } }}
代码片段1
0 条评论
下一页