虚拟机栈-简介
注意:以下都是从网上转载过来的。如果有自己的想法,完全是猜测,不足为准。
1,虚拟机栈是什么?
每个线程都会有一个虚拟机栈,多线程就会有多个虚拟机栈。虚拟机栈里面是一个一个的栈帧(Stack Frame),每一个栈帧都是在方法执行的同时创建的,描述的是Java方法执行的内存模型。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机里面从入栈到出栈的过程。栈是先进后出的,就像递归一样,你打开一扇门,进入了房间A,在里面搞了点事情,然后需要去房间B去搞点东西,但是你又不能离开房间A,只能在房间A里开了一扇门,去了房间B,在房间B里面把事情处理好了,要想回到起点,肯定是要经过房间A的;所以你先进入了A,却是先从B出来,再从A后出来,先进后出。所以你方法A中调用了方法B,虽然是先进入了方法A,后进入了方法B,却是先从B出来,再从A出来。
在活动线程中,只有一个栈帧是处于活跃状态的,也就是说只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。
执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。
2,栈帧-局部变量表
Local Variable Table
存放方法参数和方法内部定义的局部变量。在Java编译为Class文件时,就已经确定了该方法所需要分配的局部变量表的最大容量:如下图所示的随便的一个例子
即使方法内有各种for循环、while循环等,这个最大容量也是确定的,如图所示的4个地方,只要分配这个4个东西的容量就行了;当然indexChar完全没必要定义,从性能的角度,只是为了简单说明,一旦java文件编译成了class文件后,该方法需要分配在栈上的容量都是完全可以确定的,只有堆上的容量是变化的。我猜,indexChar虽然每次循环时,都会创建一次,但是在栈里面,肯定是复用一个就行了。
3,栈帧-操作数栈
Operand Stack
当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。
它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。
好像是用来执行数据之间的操作:加减乘除等等的一个内存空间;
4,栈帧-动态链接
Dynamic Linking
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。在后面的方法调用中会详细介绍。
好像是将符号引用 -> 直接引用。
5,栈帧-方法返回地址