昨天跟大家聊过了关于JVM的程序计数器的细节实现。相比大家觉得程序计数器也不过如此吧。其实技术本无难点。故若高深也会让人感觉虚无缥缈。落入实地其实也就了了。
那今天我们开始介绍JVM的第二个重要的组成部分——栈(JAVA STACK)。
栈是什么
栈是和线程一致的内存空间且线程私有。也就是说它的生命周期是和线程是一致的。当一个方法开始执行的时候会同事在栈空间里面创建一个栈帧【Stack Frame】来存储局部变量表、操作数栈、动态链接、方法出口等信息。
每一个方法从调用直至执行完成的过程其实在栈中都是有一个对应的栈帧在虚拟机栈中同样的入栈到出栈的过程。
栈的数据结构
局部变量表:中的局部变量表存放了编译期可知的各种基本数据类型(boolean、char、short、int、float、long、double)注意:long和double是64位的长度,要占用2个局部变量空间。其余数据类型只要占用1个。
对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
动态链接:在运行时创建的直接引用称为动态链接。即程序在编译成.class文件后会有一系列的引用。这些是静态引用。而在运行时才创建的引用称为动态引用。
方法出口:方法出口分为两种。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者;另外一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出。
栈的异常
如果线程请求的栈深度大于虚拟机所允许的深度。会抛出StackOverFlowError异常。
如果虚拟机栈扩展是无法申请到足够的内存,就会抛出OutOfMemioryError异常
今天对于栈的分析就是以上的内容。以上内容其实还没有深入到虚拟机中栈的数据结构的实现。但是对于了解JVM栈的结构和状态已经是足够满足要求了。各位如果有补充的可以留言交流。也希望各位不吝赐教。今天的内容就到这里了。明天还有对于JVM的后续介绍。
我的文章每天都会在头条号首发,然后第二天转发到简书中,希望有兴趣的朋友可以关注我的头条号:[Bug制造机]
(https://www.toutiao.com/c/user/51553105950/#mid=1582105392193550)。谢谢大家的支持。
网友评论