深入理解JVM运行机制与GC机制 灰太狼 2024-03-24 13:43 17阅读 0赞 ## 虚拟机结构 ## ### 运行时数据区域(叫JVM 内存模型也可以) ### 按oracle的虚拟机规范介绍可以大致分为下面几类: 程序计数器(pc register)、Java虚拟机堆栈、堆、方法区、运行时常量池、本机方法堆栈(native方法堆栈) JVM中寄存器用于存储程序计数器的值,就是每个字节码指令左侧的数字。看到寄存器我还蛮亲切的,上学时在实验室里没少“扣”寄存器,那真是用本子记再用机器“扣”着读。那时还是写汇编(现在全忘了),代码向一个寄存器地址load一个1,move一个1在寄存器调试器上都可以立马看到,非常有意思。 最后这个本机方法堆栈其实也并不陌生,它会产生两个JVM的异常 * 如果线程中的计算需要的堆栈大小比允许本机方法堆栈更大,Java 虚拟机将抛出一个`StackOverflowError`. * 如果本机方法堆栈可以动态扩展并且尝试本机方法堆栈扩展但可用内存不足,或者如果可用内存不足以为新线程创建初始本机方法堆栈,Java 虚拟机将抛出一个`OutOfMemoryError` ### 栈帧 ### 这里指虚拟机在安排方法执行时栈帧,一个方法进入执行前都会产生一个栈帧,多个方法则按照LIFO的模式执行。 在结构上栈帧包含本地变量表、操作栈两个可具象化的块儿。除此之外,在栈帧中还需要引用运行时常量池中的变量,方法,但他们在常量池中都是以符号形式存在,这就需要依赖 **动态链接**将它们转化为具体引用来供栈帧读取。 我还是更喜欢用图形来记忆: ![format_png][] ### 从对象的创建分析JVM执行流程 ### 准备一个简单的java文件,实现创建一个对象的代码: ![format_png 1][] * 1.在class加载前,先启动虚拟机 。虚拟机启动后,堆,方法区(及常量池)都会创建完成 * 2.创建一个线程栈来执行方法 * 3.外部需要一个类加载器,来加载Class到方法区 * 4.执行main方法前,将押入方法栈帧,设置好操作数栈,本地变量表大小。 完成准备工作后就像下图的样子: ![format_png 2][] 这里的 Hello 就是类名字符串,其引用将通过动态链接引入到栈帧 * 5.执行main方法 需要一个外部的执行引擎,来修改程序计数器 以第一个指令 new 作图 计数器 0: new : 创建一个对象,并将其引用值压入栈顶 在堆区创建一个对象\[分配内存\],将其引用入栈 : ![format_png 3][] 后续就不用图了因为准备工作都完成了,直接看指令 * 计数器 3: dup: 复制栈顶数值并将复制值压入栈顶 * 计数器 4: invokespecial: 调用超类构造方法,实例初始化方法,私有方法 这里会进入到构造器执行,也就需要创建新的栈帧。 ![format_png 4][] 从构造方法指令可以看到得构造方法的 栈容积1,本地变量表大小1 ,押入新栈帧: ![format_png 5][] 0: aload\_0 :将第0个引用类型本地变量推送至栈顶 1: invokespecial :调用超类构造方法 4: return :出栈 7: astore\_1: 将栈顶引用型数值存入第1位本地变量 这里将栈的引用存入1位变量中 到这里才完成了hello = new Hello() 这行代码的执行 ![format_png 6][] 看来创建一个对象最少需要4步指令,如果要赋值给另一个变量还需要额外增加2步 ### Class生命周期与对象生命周期(粗略了解) ### > [JVM类加载过程][JVM]:(装载、校验、准备、解析、初始化、使用、卸载) > > [Java对象在JVM中的生命周期][Java_JVM]: > > * 1 创建阶段(Created) > * 2 应用阶段(In Use) > * 3 不可见阶段(Invisible) > * 4 不可达阶段(Unreachable) > * 5 收集阶段(Collected) > * 6 终结阶段(Finalized) > * 7 对象空间重分配阶段(De-allocated) ## GC(Automatic Garbage Collection) ## > 垃圾回收设计原理的官方介绍文档:[Java Garbage Collection Basics][] > > GC root的种类:[Garbage Collection Roots][] > > 重点关注: > > * 系统Class > * Thread Block:被存活线程引用的对象 > * Thread:已启动但未停止的线程 > * Finalizable:在终结器队列中的对象 > * Busy Monitor:作为同步监视器或调用 wait() 或 notify() 的对象 > * Java Local:被线程栈引用的方法内的局部变量 > > 在Heap中的对象,其组成结构中包含一个age块,用于标记其存活年龄。 ### Heap 分区 ### 整个垃圾回收机制要集合Heap分区与不同的GC算法来一起看。先看heap分区结构 ![format_png 7][] 从左往右分别是:新生代、老年代与永久代。YG区域又细分为 eden,与两个survivor space 区域,这里比较好理解。 eden区都是新创建的对象,在eden内存区满时会触发小型GC,幸存的对象将移至S0,根据age累计不同逐渐移动到S1,当判定为长期存活的对象将移动到老年代。 小型GC往往会很快完成,但小型GC也是“Stop the world Event”即阻塞全部线程的执行。 老年代为主要垃圾回收,也是“Stop the world Event”,其影响时间会更长,主要由老年代的垃圾收集器决定。 永久代包含JVM所需的元数据,描述应用程序中使用的类,方法,跟随JVM运行时需要引入的类进行递增填充。简单可以理解为永久代是专门给JVM存储类与方法的描述信息用的,比如ClassLoader加载的类信息应该就在这里吧。这很容易误以为永久代就是方法区(永久代是Heap中的块,而方法区是与Heap同级的)。 永久代也会参与垃圾回收,如果 JVM 发现不再需要这些类并且其他类可能需要空间,则这些类可能会被收集(卸载)。 ### 与Heap分区对应的GC算法 ### > 优秀的个人文章:[图解 Java 垃圾回收算法及详细过程][Java] * 新生代取整体采用的是标记+复制清理法: Eden GC 后将幸存者复制到S0,Eden再次GC后 如果S0满了,则将 Eden存活的与S0存活的一起复制到S1区域,同时清空Eden与S0区域。 新建对象通常量比较小,所以Eden小型GC开销相对较小,采用复制清理可以释放出整块的内存空间,避免内存碎片化。 ![format_png 8][] * 老年代采取标记+压缩算法(或者叫标记+整理更好理解) 在回收完被标记的对象后后产生较多的碎片内存,导致无法释放出整块的内存用于创建大的对象。此时采取压缩算法对存活的对象进行重排,释放出整块的内存区域。 开销:当内存中存活对象多,并且都是一些微小对象,而垃圾对象少时,要移动大量的存活对象才能换取少量的内存空间,从而引发频繁的GC,进而造成应用卡顿。 ![format_png 9][] 到这里,此次对JVM知识的回顾就结束了 [format_png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/d1acf1c8b4be411cb5521f85ccbcd6e1.png [format_png 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/3d5a0882f7b14148a7686db5d02876f4.png [format_png 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/6806630de4f948f7ad2239a6f315c973.png [format_png 3]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/cb3ac433fdf14ebe994014655aeda261.png [format_png 4]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/311e4d47f3894b428250ee040d10cb57.png [format_png 5]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/26c1694c69744f39813caeb459605d7f.png [format_png 6]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/d50ec820240140ce800ab4b960a7bbed.png [JVM]: https://juejin.im/post/6844903564804882445 [Java_JVM]: https://juejin.im/post/6844903652507779086 [Java Garbage Collection Basics]: https://link.juejin.cn?target=https%3A%2F%2Fwww.oracle.com%2Fwebfolder%2Ftechnetwork%2Ftutorials%2Fobe%2Fjava%2Fgc01%2Findex.html [Garbage Collection Roots]: https://link.juejin.cn?target=https%3A%2F%2Fhelp.eclipse.org%2Flatest%2Findex.jsp%3Ftopic%3D%252Forg.eclipse.mat.ui.help%252Fconcepts%252Fgcroots.html%26resultof%3D%2522%2567%2561%2572%2562%2561%2567%2565%2522%2520%2522%2567%2561%2572%2562%2561%2567%2522%2520 [format_png 7]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/d5525621fb9744368bedeae0c2a0f226.png [Java]: https://link.juejin.cn?target=https%3A%2F%2Fxie.infoq.cn%2Farticle%2F9d4830f6c0c1e2df0753f9858 [format_png 8]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/3f84187c36954b6dae5be569c9eb5a9d.png [format_png 9]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/24/84c0730c60364eb79781dca1c6d77c7b.png
相关 深入理解Java虚拟机(JVM):内存结构与运行机制示例 Java虚拟机(JVM)是运行Java代码的平台。它对硬件资源进行了抽象,使得开发者可以专注于编写应用逻辑,而不必关心底层环境。 下面我们将重点介绍JVM的内存结构以及运行机 亦凉/ 2024年09月12日 02:51/ 0 赞/ 8 阅读
相关 深入理解JVM运行机制与GC机制 虚拟机结构 运行时数据区域(叫JVM 内存模型也可以) 按oracle的虚拟机规范介绍可以大致分为下面几类: 程序计数器(pc register)、Java虚拟机 灰太狼/ 2024年03月24日 13:43/ 0 赞/ 18 阅读
相关 【JVM】(三) 深入理解JVM垃圾回收机制(GC) 文章目录 前言 一、死亡对象的判断方法 1.1 引用计数算法 1.2 可达性分析算法 二、垃圾回收算法 2.1 标 超、凢脫俗/ 2023年10月14日 11:16/ 0 赞/ 24 阅读
相关 JVM-GC回收机制 目录 1.判定垃圾 1.引用计数 2.可达性分析 2.清理垃圾 1.标记清除 2.复制算法 3.标记整理 4.分代回收 ------------------ 小鱼儿/ 2023年10月10日 17:07/ 0 赞/ 3 阅读
相关 理解JVM和GC回收机制 一、JVM是什么? java虚拟机(java virtual machine,JVM)一种能够运行java字节码的虚拟机。作为一种编程语言的虚拟机,实际上不只是专应用于j 深藏阁楼爱情的钟/ 2023年07月24日 02:19/ 0 赞/ 55 阅读
相关 深入理解JVM的内存结构及GC机制 转载:[深入理解JVM的内存结构及GC机制][JVM_GC] 一、前言 JAVA GC(Garbage Collection,垃圾回收)机制是区别C++的 落日映苍穹つ/ 2022年12月11日 07:54/ 0 赞/ 151 阅读
相关 【深入理解JVM】JVM垃圾回收机制 最近又回头翻了翻《java编程思想》。有关垃圾回收机制的问题还没有总结过,刚好今天周六,总结一下吧。 1、垃圾回收的目的 垃圾回收的目的是查找和回收(清理)无用的对象, 末蓝、/ 2022年07月18日 00:29/ 0 赞/ 223 阅读
相关 深入JVM内核(二)——JVM运行机制 由于之前看的容易忘记,因此特记录下来,以便学习总结与更好理解,该系列博文也是第一次记录,所有有好多不完善之处请见谅与留言指出,如果有幸大家看到该博文,希望报以参考目的看浏览,如 谁借莪1个温暖的怀抱¢/ 2022年05月20日 03:23/ 0 赞/ 222 阅读
相关 JVM及GC机制 一、概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回 绝地灬酷狼/ 2022年04月12日 09:55/ 0 赞/ 227 阅读
还没有评论,来说两句吧...