线程栈-当前栈帧
假如运行以下Math.hava类
package com.cjc.classload; public class Math { public static final Integer COUNTAGE = 666; public static User user = null; public int count(){ //一个方法对应一个当前栈帧 int a = 1; int b = 2; int c = (a + b)*10; return c; } public static void main(String[] args){ Math math = new Math(); math.count(); user = new User(); } }
那么栈中是如何运作的。
首先将Math.class文件反汇编并存放在Math.txt文件中(javap -c Math.class > Math.txt),可以看到count()方法的代码执行过程如下
接下来通过查询jvm指令(具体百度一下就可以),这里说一下代码中几句的意思:
iconst_1意思是将int类型常量1压入栈,
istore_1意思是将int类型值存入局部变量1,
iload_1意思是从局部变量1中装载int类型值,
iadd意思是执行int类型的加法,
bipush意思是将常数放入操作数栈,
imul意思是执行int类型的乘法。
接下来一句一句来演示:
iconst_1:将int类型常量1压入操作数栈
istore_1:在局部变量表中开辟空间保存a变量,再将操作数栈中的1出栈并赋给a
iconst_2:将int类型常量2压入操作数栈
istore_2:在局部变量表中开辟空间保存b变量,再将操作数栈中的2出栈并赋给b
iload_1:从局部变量1也就是a变量装载1入操作数栈
iload_2:从局部变量2也就是b变量装载2入操作数栈
iadd:从栈顶弹出两个int类型的数进行相加操作,结果再入栈
bipush:将常量值10入栈
imul:从栈顶弹出两个int类型的值进行乘法操作,结果再入栈
istore_3:在局部变量表中开辟空间保存c变量,再将操作数栈中的30出栈并赋给c
iload_3:从局部变量3也就是c变量装载30入操作数栈
ireturn:将操作数栈中的int类型的数30返回
不是结尾的总结:
1、堆和方法区是线程共享的;栈、本地方法栈、程序计数器是线程私有的。
2、栈的默认内存大小是1M。可以通过-Xss+大小设置,如设置为-Xss128k
3、栈中局部变量表若存储的是引用类型变量如对象等,则存的是地址值,指向堆中的对象。
4、操作数栈:就是存放接下来要被操作的数,可以理解为临时存放区。
5、动态链接:在程序运行期间将符号引用替换为直接引用的过程就是动态链接。
6、方法出口:指向方法结束后接下来要执行的代码。