一.基本概念
虚拟机栈描述的是java方法执行的动态内存模型:每个方法从执行都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从执行到结束,都对应一个栈帧的在虚拟机栈中的入栈和出栈。特点:线程私有。
Class Text{
public static void sleep(){
goBed();
Boolean isSleep = true;
if(isSleep){
System.out.println("Sleep....");
}
int number1 = 1;
int number2 = 2;
int number3 = number1 + number2;
}
public static void goBed(){
Boolean isGobed = true;
if(isGobed){
System.out.println("goBed....");
}
}
public static void main(String[] args){
sleep();
}
}
以上述程序为模板其虚拟机栈运行如图
虚拟机栈遵循LIFO的思想,当main被调用时入栈,当main调用sleep时栈帧2入栈,依次类推。
当goBed函数执行完,栈帧3出栈,依次类推。
每次的栈帧入栈操作对应着虚拟机栈的内存消耗,当栈的内存消耗完时,方法则不能进行调用这时便会出现stackOverFlowError,即内存溢出。
常规下栈的内存是多少呢,每个机器的默认栈内存不大一样大概2m左右,可以通过定义数组的大小进行估算。当然也可以自己设置栈内存的大小(在后面栈溢出问题将演示).
栈里面的变量表和操作数栈他们之间的联系是什么。以栈帧3为类。
操作数栈是一个用来保存执行过程中的运算值的功能(LIFO)
如图是一个概念演示。
returnAddress类型是为字节码指令jsr、jsr_w和ret服务的,它指向了一条字节码指令的地址。在Class文件中的常量池持中存有大量的符号引用。字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数。这些符号引用一部分在类的加载阶段(解析)或第一次使用的时候就转化为了直接引用(指向数据所存地址的指针或句柄等),这种转化称为静态链接。而相反的,另一部分在运行期间转化为直接引用,就称为动态链接。
import java.lang.Integer
public Test{
}
java文件编译时不知道Integer类的真实地址,它加入用Integer这个名词来代替的话,这个Integer就可以理解为符号引用,当Test类被装载器装载时,通过虚拟机就可以获得Integr真实的地址,这真实地址就是直接引用。