JVM虚拟机栈大集合
一个方法相当于一个栈帧,下面进行结构和过程解析:
栈帧包括结构:局部变量表,操作数栈,动态链表,返回地址,对象实例引用,变量槽.....
1.局部变量表
说白了就是存放方法内部定义的局部变量(8大基本数据类型),(String引用类型),(对象引用<reference类型>),(指向一条字节码指令地址<returnAddress类型>)
8大基本数据类型:int、short、byte、double、char、boolean、float、long
String引用类型:String是个final类和八大数据类型对应的引用类型是一样一样的。
对象引用<reference类型>:相当于给对象指定类型,告诉JVM中的GC回收对象的方式,这个实际开发中很少用到
注(重点):其实讲了这么多,可能对变量,常量,String引用类型,八大数据类型的封装类,常量池.....他们的存放位置在哪?
首先先区分变量和常量的区别
常量:常量代表程序运行过程中不能改变的值。也就是用final修饰
例如:final double PI = 3.14;
变量:变量是程序运行中,其值可以改变量
例如:double PI = 3.14;
定义在类中方法外:
1.成员变量(非静态的)(八大基础数据类型)和常量(非静态的)(final定义的八大基础数据类型)都在堆
2.成员变量(静态的)(八大基础数据类型)和常量(静态的)(final定义的八大基础数据类型)都在方法区,在jdk1.8的时候通过HotSpot技术移到了元空间,元空间在本地内存中。
3.String常量池在jdk1.8的时候通过HotSpot技术移到堆中。
4.String成员变量分配在堆,这个声明是在方法区,实际对象是在堆,中间只是个引用。
5.常用的八大引用类型,在范围内的分配在方法区内 范围外(New实例化)的分配在堆,范围外的声明是在方法区,实际对象是在堆,中间只是个引用。
6.new实例化存放在堆,声明是在方法区,实际对象是在堆。
定义在类中方法内:
1.局部变量(包括静态的)(八大基础数据类型)和局部定义常量(包括静态的)(final定义的八大基础数据类型)都是在栈中
2.String分配在堆,声明是在栈,实际对象是在堆,中间只是个引用。
3.常用的八大引用类型看数据范围,因为有自动拆装箱,在范围内的分配在栈 范围外(New实例化)的分配在堆,声明是在栈,实际对象是在堆,中间只是个引用。
4.new实例化存放在堆,声明是在栈,实际对象是在堆,中间只是个引用。
所以这里就涉及到地址和值的问题,也就是==和equals的区别。
2.动态链接
指在字节码文件中,常量池指向调用方法的引用,意思也就是,在方法中调用方法,给被调用的方法一个标识,告诉你们这是个方法,和其他的信息区别开。
3.返回地址
这个说白了,就是程序要退出这个方法了,要告诉栈帧,我要退出去了,回到被调用的位置,你要帮我保存一下方法执行中处理的信息,异常退出就不用保存了,然后程序计数器指向下一条指令开始执行。在我们平时Debug就知道,当一个方法调用完毕后,最后会回到调用的位置,也就是入口位置。
3.操作数栈
HotSpot提出了栈顶缓存技术,目的是为了减少频繁使用入栈和出栈的指令,减少了IO的开销
运行过程:
1.这里的操作数栈仅仅只是作为一个缓存
2.变量赋值,首先数值入栈,然后再出栈找到对应局部变量表里面的下标
3.任何需要进行计算的数据都是先入栈再出栈进行计算后,结果再入栈,然后再出栈找到对应局部变量表里面的下标。