专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 一文吃透JVM栈

一文吃透JVM栈

更新时间:2020-10-09 17:30:54 来源:动力节点 浏览1215次

JVM栈,全称为Java 虚拟机栈,线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。


当程序开始执行时,由于只有一个main线程,因而JVM只需要为main线程分配好栈区的内存(话句话说如果有多个线程,自然就会有多个栈区,并且为各自线程私有)。main继续执行,就会遇到main()方法,遇到之后呢!JVM又会在栈区当中再划出一个小块来存放main()方法执行过程的数据,这一小块区域也就是栈帧。main()方法执行过程中又有一个add()方法出现了,同样地,JVM又会再为add()分配一个栈帧,同时压入到栈区,以后再遇到其他方法也是如此。当然,方法在执行完成之后,便会弹出并释放内存,当线程中栈区的所有方法都返回之后,程序也就算是执行完毕了。


当我们扯开栈区,撕开栈帧,一不小心,局部变量表、操作数栈、动态链接、方法出口......哗啦啦地散落一地。

image.png


捡起add()栈帧的局部变量表和操作数栈就可以看到这样一个画面,在执行例子中add()方法中的三行代码时,局部变量表和操作数栈的一个变化过程:首先,执行int a = 3;局部变量表中会分配出一个int区域,表示为a;同时iconst命令使得操作数栈中压入了常量3,然后再由istore命令将3弹出,赋值给局部变量表中a。同样,int b = 4; 这一行代码也是如此。然后,int c = a + b;从右往左开始,先执行a + b,也就是iload命令从局部变量中取出a、b对应的值,再将iadd后的值push进操作数栈中,剩下的便是int c = 7的操作了。


通过上面的例子,就很容易明白;局部变量表,顾名思义就是存放每个方法中的局部变量(即编译器可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址))所在处,如图中的a、b。操作数栈,也就是存放的就是方法当中的各种操作数的临时空间,又如栗子中的3、4。


动态链接:Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以指向常量池的引用作为参数,而将部分符号引用在运行期间转化为直接引用,这种转化即为动态链接。这个解释当中会涉及到许多概念,比如常量池、符号引用等,要想理解这些概念,就需要去了解class文件的结构,内容太多就不在这里详细描述了。


方法出口:简单来说,就是用于标记当前方法执行完成之后,应该返回到下一条指令执行位置。比如就上面的栗子而言,add()在执行完毕之后,就应该返回到e1.add()之后继续执行main()后面的代码。


上面就是对JVM栈的全面讲解,还没有完全弄懂的小伙伴可以通过观看本站的Java零基础教程学习更多的JVM知识。


提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>