| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> JVM-虚拟机栈详解 附面试高频题 (手画多图)!!!深入浅出,绝对值得收藏哈!!! -> 正文阅读 |
|
[系统运维]JVM-虚拟机栈详解 附面试高频题 (手画多图)!!!深入浅出,绝对值得收藏哈!!! |
来源: 作者: 原因: JVM-虚拟机栈详解 附面试高频题 (手画多图)一、虚拟机栈概述先给大家来看一下 运行时数据区的图示👇 如果大家没咋了解Java的内存结构,就常会粗粒度地将JVM中的内存区理解为仅有Java堆(heap)和Java战(stack)?为什么?🤳🧐 首先栈是运行时的单位,而堆是存储的单位
不过今天我们讨论的是虚拟机栈。堆的文章之后才更👨?💻。
注意: 🏂
二、栈帧2.1、栈与栈桢:每一个方法的执行到执行完成,对应着一个栈帧在虚拟机中从入栈到出栈的过程。 👨?🚀 2.2、栈帧概述
如下图: 左边是通过 我们通过上图可以看到,在编译过程中,已经给每个栈桢分配好了 操作数栈 的深度啊,局部变量表的大小等等。 局部变量表是4的原因:虽然我们在这个方法中只定义了a,b,c 三个局部变量,但是大家还记得
用法 我们将一个类编译完后,兄弟们,编译没有问题吧。不行,感觉还是要贴出来哈。 编译完成之后。我们打开 菜单中 -->view 选项。 里面的具体的东东靠大家慢慢发掘了哈,我们还是回归正文啦。给大家个Oracle 的JVM 官方规范。方便指令的查找解释哈。 2.3、想一想我们遇到过哪些与栈相关的异常?Java 虚拟机规范允许Java栈的大小是动态的或者是固定不变的。 🏄?♂? 1、如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个``StackoverflowError `异常。(栈溢出) 举个栗子:相信大家肯定学过递归算法,如果它一直没有出口,结果就是栈溢出。🚣?♂? 2、如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那Java虚拟机将会抛出一个 2.4、设置栈内存大小刚刚大家也看到了,我们可以使用参数 -Xss选项来设置线程的最大栈空间,栈的大小直接决定了函数调用的最大可达深度。
2.5、局部变量表概述:
局部变量表中的变量只在当前方法调用中有效。在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。 👨?💻👨?🚀🤹?♂?🤽?♂?🏌??♂?🐱?🚀🐱?🐉🎊🧬🚀🛫🚢🛸🚤?🌈🌊 局部变量的存放 Slot(变量槽)参数值的存放总是在局部变量数组的index0开始,到数组长度-1的索引结束。🤭 局部变量表,最基本的存储单元是Slot(变量槽)局部变量表中存放编译期可知的各种基本数据类型(8种),引用类型(reference),returnAddress类型的变量。 在局部变量表里,32位以内的类型只占用一个slot(包括returnAddress类型),64位的类型(long和double)占用两个slot。 JVM会为局部变量表中的每一个Slot都分配一个访问索引,通过这个索引即可成功访问到局部变量表中指定的局部变量值。 静态变量与局部变量的对比变量的分类:😜
🎅 我们知道类变量表有两次初始化的机会,第一次是在“准备阶段”,执行系统初始化,对类变量设置零值,另一次则是在“初始化”阶段,赋予程序员在代码中定义的初始值。 和类变量初始化不同的是,局部变量表不存在系统初始化的过程。这意味着如果创建了局部变量,并且在使用前不对它进行显示赋值,那么将无法通过编译。 在栈帧中, 2.6、操作数栈1、每一个独立的栈帧除了包含局部变量表以外,还包含一个后进先出(Last - In - First -Out)的 操作数栈,也可以称之为 表达式栈(Expression Stack)🤪 操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)和 出栈(pop)
3、每一个操作数栈都会拥有一个明确的栈深度用于存储数值,其所需的最大深度在编译期就定义好了,保存在方法的Code属性中,为maxstack的值。 4、操作数栈的每一个元素可以是任意Java数据类型,32位的数据类型占一个栈容量,64位的数据类型占2个栈容量,且在方法执行的任意时刻,操作数栈的深度都不会超过max_stacks中设置的最大值。 5、操作数栈并非采用访问索引的方式来进行数据访问的,而是只能通过标准的入栈和出栈操作来完成一次数据访问 6、如果被调用的方法带有返回值的话,其返回值将会被压入当前栈帧的操作数栈中,并更新PC寄存器中下一条需要执行的字节码指令。
我想看完这个gif动图 ,我想大家大概能够明白操作数栈是一个什么样的流程了吧,或者已经明白了吧。如果没有明白的话,可以留言评论哈。 2.7、动态链接概述
在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(symbolic Reference)保存在class文件的常量池里。
比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用。
1、代码部分 2、通过
链接静态链接: 当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期克制,且运行期保持不变时,这种情况下降调用方法的符号引用转换为直接引用的过程称之为静态链接 动态链接: 如果被调用的方法在编译期无法被确定下来,也就是说,只能够在程序运行期将调用的方法的符号转换为直接引用,由于这种引用转换过程具备动态性,因此也被称之为动态链接。
2.8、方法返回地址存放调用该方法的pc寄存器的值。当一个方法开始执行后,只有两种方式可以退出这个方法:
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。 异常表:方法执行过程中,抛出异常时的异常处理,存储在一个异常处理表,方便在发生异常的时候找到处理异常的代码 本质上,方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。 正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的不会给他的上层调用者产生任何的返回值。 2.9、一些附加信息栈帧中还允许携带与Java虚拟机实现相关的一些附加信息。例如:对程序调试提供支持的信息。
面试
自言自语这两天河南发生了大暴雨,希望他们平安度过!!! 兄弟们,还是一起躺平吧。内卷太累辣吧。。。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 0:56:37- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |