面试题分享系列之你能说一下GC垃圾回收机制吗

简介: 经典面试题

面试官问调优的话, 你先不要说调优,因为讲调优之前需要一些前置的内容,可以先从垃圾回收机制的类型开始讲起,以及GC的优化点在哪里?


一般讲完30分钟就过去了,但前提是都理解哈,不建议死记硬背.


PS + PO


这是JDK1.8默认的垃圾回收器. 他的特点是稳定性和吞吐较高.


是一款物理分代逻辑分代的垃圾回收期.


具体的区域分为伊甸园 幸存者 老年代 三大区域.


在讲具体回收顺序月之后我们先得讲一些垃圾回收算法.


引用计数算法:这个算法使用了指针的思想,有用的类互相引用,如果没有被引用到的,就默认是垃圾 进行回收.


但是有时候会出现浮动垃圾,也就是垃圾引用垃圾,会造成内存泄漏的情况,但是好处是实现简单,适用于python和GO.


根可达算法:这个算法在效率和实现难度中做了一个取舍,用较为复杂的算法实现难度换取了相对引用计数来说更高的性能,可以通过根节点获取下面所有的子节点,通过快速定位对象,来达到一个较快的效率.


标记清除算法:这个算法和我们的扫雷游戏很类似,在一个个的方格里里,你标记哪个是地雷,在标记结束之后,会对这些被标记的空间进行清除,但是这里包含着一个致命的缺点,就是他的空间是碎片化的,是非常浪费空间的.


标记压缩算法:这种方法可以压缩我们的空间,但是是用空间换时间,因为从效率上来说他是一边进行垃圾标记,一边进行压缩的,最后再进行清除,这样内存也是连续性的,但是显而易见的是他的缺点也十分明显,那么就是他的效率十分的低下.


现在说到我们最后一种算法了,这种算法叫做拷贝算法,也是我们目前应用在伊甸园区和幸存者区的算法.


首先在我们的JVM分代模型当中,分为伊甸园区(新生代),幸存者区(from,to),老年代.


举个例子现在我们往年轻代中放入10个对象,最后比如存活下来了一个,那么这一个对象就会被放到伊甸园区from区当中,这其中使用的就是根可达算法,根可达算法通过根节点像毛线团一样,从头抽到尾,把有用的对象都抽取过来,然后剩下在年轻代中的就都是等待被回收的垃圾了,那么他这时候如果执行一个内存擦除的功能,他的效率是非常高的,只需要给内存一个开始位置值和一个偏移量就行了,当这样循环往复往里面存取了之后,from区会进行垃圾回收,这里会运用到拷贝算法,虽然会损耗一部分的空间,但是可以提高我们YGC的效率,通过拷贝算法来把幸存的内存从from区转移到To区,之后from区和年轻代一起进行一次内存擦除,之后To区域满了之后会和From互换,保证To区的绝对干净,然后进行内存擦除,此时空间的默认比值为8:1:1,所以只会造成百分之10的浪费,也可以理解为使用了复制算法的变种,不等复制算法,当互换到达默认15次之后,这个是个参数可以设置,那么剩余的数据就会被放入到老年代当中,当老年代满了之后就会执行FullGC,出现STW.


补充:特别大的大对象以及动态年龄满足的对象会直接进入老年代.  也是导致FULL GC的罪魁祸首之一.


而我们JVM的调优 就是针对这个STW的次数 和 时间长度进行调优的.


优化点:内存太大清理不过来建议更换G1,内存小调整阈值看看,CPU100的话 根据jmap看对象排查一下代码,或者是使用arthas.


CMS


CMS是我们垃圾回收机制中里程碑级别的存在.这个里程碑指的是他开创了一种新的模式,加入了在流程上实现并发线程这一概念,可以一边执行业务线程一边执行垃圾回收线程,具体的执行步骤为标记根节点->标记子节点->重新标记->垃圾清除,其中前2步我们应该很容易理解,它指的其实就是从根节点出发,能够标记到的表示都不是垃圾,而第三步可能就不太明白了,当初我也上网查阅了一下OpenJDK官网上的资料,里面简要的介绍了一下我们在重新标记这一步骤所做的操作,英文翻译过来大致的意思就是减少我们并发执行下所做的变动,可以理解为减少一下容错率,最后一步就是将标记的垃圾进行清除了.


在这其中我们会引入一个算法,也就是大名顶顶的三色标记算法,里面变为黑色,白色,灰色三色. 白色代表未扫描到,灰色代表当前节点已扫描到但没有全部扫描完毕,黑色代表节点下全部扫描完毕.


举个例子有个student对象,其中有2个属性name和age.根据三色标记算法,CMS先会去寻找根节点student,然后依次给下面的子属性上色,如果没有全部上色完毕,那么根节点就是灰色,如果还没有寻找,那么就是白色,如果全部寻找到了,那么就是黑色,所以一个完全被标记的学生对象,就应该是全黑的.


听起来CMS好像很高大上,但是实际上它的问题还是很多的,现在我们来说说它的问题


1.浮动垃圾. 如果在清理期间,内存因为浮动垃圾满了,那么之后我们的CMS就会调用单线程进行FULL GC,这个效率是非常低的.


2.内存碎片化.如果在清理期间,塞入大对象的话,因为CMS使用的是标记清除算法,所以会出现内存碎片化的情况,导致内存利用率不是特别高,如果此时有大对象进来把空间撑爆了,那么之后我们的CMS也会调用单线程进行FULL GC,这个效率是非常低的,同上,至今不知道CMS为什么要用单线程进行FULL GC,听说是研发资金的原因,为了以后退出更好的GC.


应对CMS的问题,最好的建议就是切换垃圾回收器,把CMS切换成G1,因为我们业务卡顿的很大概率可能不是调优可以解决的,如果实在是需要使用CMS并且要对其进行优化的话,建议调整他的阈值或者是加大内存,尽可能的让他不要进行FULL GC,这样就不会出现单线程清理垃圾的问题了.


G1


G1可以理解为CMS的升级版本,他的响应时间大致为200ms,大致流程和CMS差不多,只不过GC分为了YGC,MixedGC和FullGC,中间多了一个混合回收,只不过他实现了逻辑上的分区,这里引入了一个新的名词Region区,不再是按照以往的垃圾回收器用代进行分配了,这里是分成一个个的Region区,每个区都分别代表伊甸园区,幸存者区或者老年代区,大对象区等等,这个数量是不固定的,并且G1引入了自动优化这一个概念,在之前我们的年轻代的资源空间需要我们根据具体的业务场景去调整他的大小,但是在G1当中我们无需指定他的范围,他会自动根据我们的YGC次数来进行微调,其中引入了Cset和Rset的概念,其中Rset可以帮我们快速定位引用对象之间的关系,每个Region区中都有一个Rset,他相当于是位图,里面有一个个的卡表,其中1代表了被引用,0代表没有被引用,没有被引用的会被放入Cset当中,这是一个回收集合,在MixedGC当中被用来回收,他会优先回收垃圾比较多的region区,大大加快了我们G1的回收速度,也是优化的一个亮点.


总结优点:


1.使用了copying算法,避免了空间的碎片化.


2.使用了位图Rset和垃圾收集集合Cset的概念,优化了垃圾回收的速度.


3.自动对年轻代进行优化.


4.混合GC优先会回收数据量比较大的Region区.


5.G1 能够减少大量的浮动垃圾 运用的是SATB快照技术 在并发标记会进行快照,记录下变更颜色过的引用,然后把这些引用重新扫描一遍,最大限度减少浮动垃圾的产生.


image.png


优化点:调整混合回收的阈值,尽量避免FullGC的出现.


FloatingGarbageObjectscandieduringaG1collectionandnotbecollected. G1usesatechniquecalledsnapshot-at-the-beginning (SATB) toguaranteethatallliveobjectsarefoundbythegarbagecollector. SATBstatesthatanyobjectthatisliveatthestartoftheconcurrentmarking (amarkingovertheentireheap) isconsideredliveforthepurposeofthecollection. SATBallowsfloatinggarbageinawayanalogoustothatofaCMSincrementalupdate.
//补充一下很多网上的都说G1是没有垃圾的,实际上他是有的,具体详见openJDK官网    //https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc.html



调优场景


PS + PO 业务非常卡顿,首先升级了一下内存,升级为了100G,之后发现好了很多,但是卡顿时间变长了,最后使用了G1,连续6个月正常.

目录
相关文章
|
21天前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
2天前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
10 0
|
26天前
|
监控 算法 Java
深入理解Java中的垃圾回收机制(GC)
本文将探讨Java的自动内存管理核心——垃圾回收机制。通过详细解析标记-清除算法、复制算法和标记-整理算法等常用垃圾回收算法,以及CMS、G1等常见垃圾回收器,帮助读者更好地理解Java应用的性能优化和内存管理。同时,探讨分代收集、分区收集等策略在实际项目中的应用。结语部分总结了垃圾回收机制在Java开发中的重要性,并展望了未来可能的发展。
33 0
|
2月前
|
缓存 监控 Java
"Java垃圾回收太耗时?阿里HBase GC优化秘籍大公开,让你的应用性能飙升90%!"
【8月更文挑战第17天】阿里巴巴在HBase实践中成功将Java垃圾回收(GC)时间降低90%。通过选用G1垃圾回收器、精细调整JVM参数(如设置堆大小、目标停顿时间等)、优化代码减少内存分配(如使用对象池和缓存),并利用监控工具分析GC行为,有效缓解了高并发大数据场景下的性能瓶颈,极大提升了系统运行效率。
58 4
|
2月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
3月前
|
缓存 监控 算法
Java面试题:描述Java垃圾回收的基本原理,以及如何通过代码优化来协助垃圾回收器的工作
Java面试题:描述Java垃圾回收的基本原理,以及如何通过代码优化来协助垃圾回收器的工作
76 8
|
3月前
|
监控 算法 Java
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
Java面试题:如何在Java中触发一次Full GC?请详细解释垃圾回收机制和知识
277 4
|
2月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
4天前
|
JSON 安全 前端开发
第二次面试总结 - 宏汉科技 - Java后端开发
本文是作者对宏汉科技Java后端开发岗位的第二次面试总结,面试结果不理想,主要原因是Java基础知识掌握不牢固,文章详细列出了面试中被问到的技术问题及答案,包括字符串相关函数、抽象类与接口的区别、Java创建线程池的方式、回调函数、函数式接口、反射以及Java中的集合等。
13 0
|
2月前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。