hi 大家好,我是 DHL。公众号:ByteCode ,专注分享有趣硬核原创内容,Kotlin、Jetpack、性能优化、系统源码、算法及数据结构源码网站、动画、大厂面经

全文分为 视频版文字版

视频版:

通过语音和动画,能够更加直观的看到虚拟机linux,内存记录方法调用和返回过程。

bilibili 地址: b23.tv/TQXL4xx

文字版

我们在写代码的时候有没有思虚拟机怎么使用考过 方法如何调用方法执行完之后如jvm内存模型何返回内存如何记录方法调用过程 。而这也动画是今天这多线程的实现方式篇文章重点内容。

方法调用和返回过程涉及到了,虚拟机栈、程序计数器、局部变量表、操作数栈、方法返回地址、动态链接等等内容,涉及到虚拟机知识点很源码交易平台多,同时这些内容也是高频面试题,所以我将拆分成多篇文章,针对每个知识点去做详细的分析。而今天这篇文章我们重点去看多线程编程内存是如何记录方法调用和返回过程。

虚拟机栈

Java 方法以栈帧的形式,运行在虚拟机栈(Java 栈)中,栈是线程私有的,程序启动的时候,会创建一个 main 线程,操作系统会为每一个jvm性能调优线程分配一段内存,线程创建的时候会创建一个虚拟机栈,虚拟机栈的生命周期和线程一样,jvm是什么意思线程结束了,虚拟机栈也销毁了。

每个 Ja动画制作软件va 方法,对应一个个栈帧,所以方法源码网站开始和结束,都是一个个栈帧入栈和出栈的过程,效果如下图所示源码中的图片

学习突破35岁焦虑,动画演示内存记录函数调用过程

栈帧

每个 Java 方法,都是一个个栈帧,每个栈帧包括了:局部变量表、操作数栈、方法返回地址、动态链接、附加信息。

学习突破35岁焦虑,动画演示内存记录函数调用过程

  • 局部变量表: 保存方法参数列表和方法内的局部变量,按照声明的顺序存储,它以数组的形式展示,如果是实例方法,索引为 0 是 this 的引用,如下图所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

索引(Slot) 名字(Name)
0 this
1 num
2 res
  • 操作数栈: 保存方法执行过程中的临时结果
  • 返回地jvm内存模型址: 保存调用该方法的 pc 寄存器的值(即 JVM 指令地址),用于方法结束时,返回调用处,让调用者方法继续执行jvm内存模型下去
  • 动态链接: 指向运行时常jvm垃圾回收机制量池中该栈帧所属方法的引用,即从常量池中找到目标方法的符号引用,然后转换为直接引用
  • 附加信息:比如程序 debug 时添加的一些附件信息(不虚拟机哪个最好用重要,不需要关心,可忽略)

这里只需要知道它们的作用即可,它们的数据结构、字节码的含义、执行过程等等,后续的文章我将会针对每个知识点去做详细的分析。

方法调用过程

先写一段方法调用的代码,首先会调用 main() 方法之后调用 fun1() 然后调用 fun2() ,如下图所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

现在我们来演示一下 Java 虚拟机执行这些 JVM 指令的过程,首先会调用 m动画片熊出没ain ()源码中的图片 方法。

main () 方法

main() 方法执行流程动画效果如下所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行多线程的实现方式指令 0: aloajvm优化d_0,从局部变量表中,读取索引为 0 的值,压入操作数栈中,因为是实例方法,所以索引为 0 的值是 this多线程并发中线程的状态 的引用

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 1: iconst源码_5 ,将常量 5 压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 2: invokevirtjvm是什么意思ual #7,常量 5 和 this 从操作数栈中出栈,然后调用 this.fun1(5)

学习突破35岁焦虑,动画演示内存记录函数调用过程

首先从常量池中jvm优化找到方法 fun1() 的符号引用,然后通过动态链接将符号引用转换成直接引用,之后调用 this.fun1(5),将方法 fun1() 作为栈帧压入虚拟机栈源码交易平台中,跳转到 fun1(),继续往下执行。

如何从常量池中找到目标方法的符号引用,然后转换成直虚拟机接引多线程是什么意思用的过程,将会在后面系列文章中详细分源码编辑器

在调虚拟机怎么使用fun源码中的图片1()多线程的实现方式前,fun1() 的局部变量表和方源码编程器法返回地址已经确定好了。

学习突破35岁焦虑,动画演示内存记录函数调用过程

进入方法 fun1 (int num)

方法 fun1源码交易平台(int num) 执行流虚拟机下载程动画效果如下所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 0: aload_0,从局部变量表中,读取索引为 0 的值,压入操作数栈中。因为是实例方法,所以索引为 0 的值是 this 的引用

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 虚拟机linux行指令 1: iload_1,从局部变量表中,读取索引为 1 变量 num源码 的值,并压入操作数栈

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 2: invokevirtual #13,num 和 this 从操虚拟机下载作数栈中出栈,然后调用 this.fun2(num)虚拟机安装教程win10

学习突破35岁焦虑,动画演示内存记录函数调用过程

首先从常量池中找到方法动画片熊出没 fun2() 的符号引用,然后通过动态链接将符号引用转换成直接引用,之后调用 this.fun2(num),将方法 fun2() 作为栈帧压入虚拟机栈中,跳转到 fun2(),继续往下执行,调用 fun2() 之前,fun2() 的局部变量表和方法返回地址已经确定好了。源码之家

学习突破35岁焦虑,动画演示内存记录函数调用过程

进入方法 fun2 (int num)源码时代

方法 fun2(i虚拟机安装教程win10nt num) 执行流程动画效果如下所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 0: iload_1,从局部变量表中,读取索引为 1 变量 nJVMum 的值,并压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 1: bipush ,将常量 10 压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 3: iadd ,num 和常量 10 从操作数栈中动画头像出栈,然后进行相加,将结果压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 4: istore_2,从操作数栈源码网站中取出结果,并赋值给局部虚拟机是什么意思变量表中索引为 2 的变量 res2

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 5: iload_2,从局部变量表中,读取虚拟机怎么使用索引为 2 的变量 res2 的值,jvm原理并压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

方法退出过程

每个方法即jvm调优是一个栈帧,每个栈帧会保存方法返回地址,执源码时代return 系列指令时,会根据当前栈帧保存的返回地址,返回到调用的位置,继续往下执行。因此会分为两种情况jvm内存

异常退出

如果出现了异常且捕获了该异常,则会从异常表里查找 PC 寄存器的地址(JVM 指令地址),返回调用处继续执行。

学习突破35岁焦虑,动画演示内存记录函数调用过程

正常退出时会做以下件事

  • 恢复上一个栈帧局部变量表、操作数栈
  • 如果有返回值,将返回值压入调用者栈帧的操作数栈,是否有返回值根据 retur源码时代n JVM 指令:
    • i动画大放映return :返回值是 booleanbytecharshortint 类型
    • lreturn :返回值是 Long源码1688
    • freturn :返回值是 Float 类型
    • dreturn :返回值是 Double 类型
    • areturn :返回值是引用类型
    • return :返回值类型为 void
  • 设置调用者栈帧源码交易平台的 JVM 指令地址
  • 当前栈帧从虚拟机栈中出栈

多线程的应用场景篇文章我们只分析正常退出流程,异常退出和正常退出的流程大致都是一样的。正常退出流程动画效果如虚拟机安装教程win10下所示。

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 方法 fun2 结束时jvm优化,执行最后一条指令 ireturn ,当前栈帧从虚拟机栈中出栈,根据当前栈帧保存的方法返回地址,返回到 fun1 ,恢复 fun1 的局部变量表、操作数栈,将返回结果 res2 保存到调用者(fun1)操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 回到方法 fun1(int num) ,执行指令 5: istore_2,变量 res2 从操作数jvm是什么中出栈,赋值给局部多线程应用场景例子变量表中索引为 2 的变量 res1

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行指令 6: iload_2 ,从局部jvm是什么意思变量表中,读取索引为 2 变量 r动画片汪汪队es1 的值,并压入操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 执行方法 fun1 最后一条指令 7: ireturn,当前栈帧从虚拟机栈中出栈jvm内存,根据当前多线程是什么栈帧保存的方动画头像法返回地址,返回到 main 方法,恢复 main 方法的局部变量表、操作数栈,将返回结果 res2 保存到调用者(main)操作数栈中

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 最后回到方法 main 中,执行最后一条指令 5: pop,操作数栈中的元素出栈

学习突破35岁焦虑,动画演示内存记录函数调用过程

  1. 动画行最后一条指令 6: return,至此所有的方动画电影法调用结束了,方法所占用的内存,也将返回给系统

学习突破35岁焦虑,动画演示内存记录函数调用过程

每次的方法调用,即是栈帧入栈和出栈的过程,同时也需要占用部分内存,用于保存局部变量表、操作数栈、方法返回地址、动态链接虚拟机是什么意思、附加信息等等。多线程并发中线程的状态

当方法执行完,即栈帧出栈,方法调用所占用的内存,也将返回给系统。


全文到这里就结束了,感谢你的阅读,如果有帮助,欢迎 在看点赞jvm内存分享 给身边的朋友。

真诚推荐你关注我,公众号:ByteCode ,持续分享硬核原创内容,Kotlin、Jetpack、性能优化、系统源码动画片少儿小猪佩奇、算法及数据结构、动画、大厂面源码中的图片经。



近期必读热门文章

  • 揭秘反射真的很耗时吗,射 10 万次耗时多久
  • 你知道 It动画片猫和老鼠erable 有多慢吗?试试它提升性能
  • 揭秘 Kotlin 1.6.20 重磅功能 Context Receivers
  • Stack Overflow 上最热多线程编程门的 10 个 Kotlin 问题
  • Android 12 已来,你的 App 崩溃了吗?
  • Google 宣布废弃 LiveData.observe 方法
  • 影响性能的 Kotlin 代码(一)
  • 揭秘 Kotlin 中的 == 和 ===

最后推荐长期更新和维护的项目

  • 个人博客虚拟机下载,将所有文章进行分类,动画片猫和老鼠欢迎前去查看 hi-dhl.com

  • KtKit 小巧而实用,用 Kotlin 语言编写的工具库,欢迎前去查看 KtKit

  • 计划建立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理分析文章,正在逐渐增加 Jetpack 新成员,仓库持续更新,欢动画片小猪佩奇迎前去查看 AndroidX-Jetpack-Practice

  • LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程题解,语言 Java 和 kotlin,包含多种解法、解题思路、时间复杂度、空间复杂度分析

学习突破35岁焦虑,动画演示内存记录函数调用过程

  • 剑指 offer 及国内外大厂面试题解:在线阅读
  • LeetCode 系列题解:在线阅读