JVM的垃圾回收机制真是通俗易懂
堆内存的划分
分为三个部分(以下名词表示同一个区):
- 新生区、新生代、年轻代
- 养老区、老年区、老年代
- 永久区、永久代
划分区域的目的
唯一目的就是优化GC性能。
如果没有分代,我们所有的对象都放在一块,GC的时候我们需要对堆的所有区域进行扫描。而很多的对象都是“朝生夕死”的,如果把创建的新的对象都放在某一地方,当GC的时候就先把“朝生夕死”对象的区域进行回收,这样就会腾出很多大的空间来。
一、新生区的垃圾回收机制
新生区分为:Eden区、Survivor0区、Survivor1区(也称为from区和to区)
其中Eden区占80%的内存空间,每块Survivor各占用10%的内存空间(如:Eden占800M,每个Survivor占100M)
1.开始时创建的对象都是分配在Eden区域中,当Eden区快满了,就会触发垃圾回收Minor GC(使用复制算法进行垃圾回收)
2.Minor GC处理后,首先会把Eden区中还存活着的对象一次性转入其中一块空闲着的Survivor区。然后清空Eden区,之后创建的对象就继续放入Eden区中了,直至下次Eden又被填满。
3.Eden再次被填满时,就会再次出发Minor GC,清理后(Minor会清理Eden区和Survivor区的内存),Eden区和存在对象的Survivor区(此时的from区)中存活的对象转移到另一块空着的Survivor区中(此时的to区),并清空Eden区和之前存在对象的Survivor区(此时变为to区了,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。)
这就是复制算法的流程。
一直要保持一个Survivor区是空的以提供复制算法垃圾回收,而这块区域的内存只占整块的10%,其他90%内存都可以被使用,课件内存利用率还是相当高的。
二、什么时候进入老年区呢?
1 经历15次GC后进入老年区
默认情况下,如果新生区中的某个对象经历了15次GC后,还是没有被回收掉,那么它就会被转入老年区。
可通过JVM参数“-XX:MaxTenuringThreshold”来设置,默认是15。
2 动态对象年龄判断
这种方法不用等到经历GC15次。
假如一批对象总大小大于当前Survivor区内存的50%,那么大于等于这批对象年龄的对象就会被转移到老年区。
例:假设Survivor0区中的两个对象都经历的3次GC(年龄3),而且这两个对象总大小50M,超过了Survivor0区内存大小的一半。那么此时Survivor0区中年龄大于等于3岁的对象就都要被全部转移到老年区。
3 大对象直接进入老年代
有一个JVM参数"-XX:PretenureSizeThreshold",默认值是0,表示任何情况都先把对象分配给Eden区。
若设置为1048576字节,也就是1M。则表示当创建的对象大于1M时,就会直接把这个对象放入到老年区,就根本不会经过新生区了。
这么做的原因:大对象在经历复制算法进行GC的时候会降低性能。
4 Minor GC后存活的对象太多无法放入Survivor区了
Minor GC后存活的对象太多,导致Survivor区放不下了,此时就会将所有的对象直接转移到老年区中。
三、老年区空间分配担保原则
执行每一次Minor GC前,JVM都先检查一下老年区可用的内存空间是否大于新生区所有对象的总大小。
原因:极端情况下,Minor GC后,新生代中所有的对象都活了下来,那就会把所有新生代中的对象放入老年区中。
- 如果说老年区可用内存大于新生代对象总大小,那么就可以放心的执行Minor GC。
- 但如果老年区内存小于新生区对象的总大小,这时候就会看一个参数:“-XX:HandlePromotionFailure”是否设置为true了。如果为true,就进入下一次判断,看老年区可用内存是否大于之前每次Minor GC后进入老年区对象的平均大小。如果老年代可用内存小于平均大小或是参数没有设置成true,那就会直接触发“Full GC”,就是对老年代进行垃圾回收,腾出空间后,再进行Minor GC,相当于对新生区、老年区统一做了一次清理。
三种情况递进理解:
1.如果Minor GC后,存活的对象<Survivor区大小,直接进入Survivor区即可;
2.如果Minor GC后,存活的对象>Survivor区大小,但<老年区可用内存,直接进入老年区;
3.若Minor GC后,此时老年区都放不下这些存活的对象了,就会触发Full GC;
如果Full GC后老年区内存还是不够用,就会导致OOM内存溢出。
四、老年区垃圾回收算法
标记整理算法
【原理】
一开始对象都是任意分布的,在经历完垃圾回收之后,就会标记出哪些是存活对象,哪些是垃圾对象,然后就会把这些存活的对象在内存中进行整理移动,尽量都挪到一边去靠在一起,然后再把垃圾对象进行清除,这样做的好处就是避免了垃圾回收后产生的大片内存碎片。
【缺点】
较为耗时,比复制算法慢10倍;
所以如果系统频繁出现Full GC,会严重影响系统性能,出现卡顿。所以JVM优化的一大问题就是减少Full GC频率。
五、垃圾回收器
新生区和老年区进行垃圾回收时是通过不同的垃圾回收器进行回收的
Seral 和 Seral Old垃圾回收器
- 分别用于回收新生区和老年区。
- 单线程运行,垃圾回收时会停止我们系统的其他线程,再执行垃圾回收(不再使用);
ParNew和CMS垃圾回收器
- 分别用于新生区和老年区;
- 多线程并发,性能更好,现在一般是线上生产系统的标配。
G1垃圾回收器
统一收集新生区和老年区,采用更加优秀的算法机制。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注猪先飞的更多内容!
原文出处:https://blog.csdn.net/weixin_50924373/article/details/123119
相关文章
- 说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核、Zend引擎、以及扩展层;PHP内核用来处理请求、文件流、错误处理等相关操作;Zend引擎(ZE)用以将源文件转换成机器语言,然后在虚拟机上运行它;扩展层是一组...2015-11-24
- 这篇文章主要介绍了 Jasper的自动检测实现的机制比较简单,依靠某后台线程不断检测JSP文件与编译后的class文件的最后修改时间是否相同,若相同则认为没有改动,但倘若不同则需要重新编译,需要的朋友可以参考下...2016-12-02
- 这篇文章主要介绍了详解C语言进程同步机制的的相关资料,文中代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-06-18
- 这篇文章主要介绍了通过实例了解Python异常处理机制底层实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-24
浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系
这篇文章主要介绍了浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-22跟我学Node.js(四)---Node.js的模块载入方式与机制
其它的如通过NPM安装的第三方模块(third-party modules)或本地模块(local modules),每个模块都会暴露一个公开的API。以便开发者可以导入。如复制代码 代码如下:var mod = require('module_name')此句执行后,Node内部会载入...2014-06-07- 这篇文章主要帮助大家更好的理解js回收机制,通俗易懂,便于大家理解,感兴趣的小伙伴们可以参考一下...2016-03-01
- 这篇文章主要介绍了c# 如何用好垃圾回收机制GC,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了JAVA 反射机制的相关知识,文中讲解的非常细致,代码帮助大家更好的理解学习,感兴趣的朋友可以了解下...2020-06-17
- 这篇文章主要介绍了教你一文搞懂Kotlin中的Jvm注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-11
- 这篇文章主要介绍了详解CocosCreator项目结构机制,只有了解这些机制后,才能更好的进行项目开发,避免潜在错误,并且快速的除错...2021-04-15
- 这篇文章主要给大家介绍了关于.NET Core中本地化机制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要介绍了HTTP浏览器缓存机制,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-22
- 这篇文章主要介绍了java应用开发之JVM运行时内存,文中附含图文示例内容分析非常简要,有需要的朋友可以借鉴参考下,希望能够有所帮助...2021-09-16
- 这篇文章详细介绍了C#垃圾回收机制,有需要的朋友可以参考一下...2020-06-25
- 这篇文章主要介绍了深入理解Java之jvm启动流程,文章内容讲解的很清晰,有对这方面感兴趣的同学可以研究下...2021-02-09
- 这篇文章主要为大家详细介绍了完善的jquery处理机制的相关资料,感兴趣的小伙伴们可以参考一下...2016-02-23
- 反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道...2020-06-25
- 这篇文章主要介绍了JVM的种垃圾回收,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-08-15
- 这篇文章主要介绍了Java 反射机制原理与用法,结合实例形式详细分析了Java反射机制的相关概念、原理、基本使用方法及操作注意事项,需要的朋友可以参考下...2021-08-25