JVM垃圾回收机制

浅记录一下关于JVM垃圾回收机制的学习内容。

目录

JVM-“分代收集”

GC过程

动态年龄判断

空间分配担保

为什么Survivor有两个区域?

如果没有Survivor会怎样?

如果只有一个Survivor会怎样?

两个Survivor

参考文档


JVM-“分代收集”

垃圾收集器大多数遵循了分代收集(GenerationalCollection)的理论进行收集。

JVM的对空间分成2个区域:年轻代、老年代

其中年轻代又分为3个区域:Eden、Survivor From、Survivor To

  • 默认情况下年轻代和老年代内存占比为1:2。可以通过参数-XX:NewRatio修改,其默认值为2。如果改为3,年轻代和老年代占比就为1:3。
  • 默认情况下Eden、Survivor From、Survivor To的占比为8:1:1。可以通过参数-XX:SurvivorRatio修改,其默认值为8。如果改为6,则占比就是6:1:1。

GC过程

1.所有年轻代首先会在Eden分区进行分配,当Eden分区满了之后会进行1次Minor GC。当某些大对象需要分配一块较大的连续空间时,会直接进入老年代。-XX:PretenureSizeThreshold参数定义多大的对象直接进入老年代)

2.第一次Minor GC后,仍然存活的对象会被复制到Survivor From区,同时对象年龄+1。此时Eden占用内存被清空。

3.第二次对Eden和Survivor From区进行Minor GC,仍然存活的对象会被复制到Survivor To区,同时对象年龄+1。此时Eden和Survivor From占用内存被清空。

4.第三次对Eden和Survivor To区进行Minor GC,仍然存活的对象会被复制到Survivor From区,同时对象年龄+1。此时Eden和Survivor To占用内存被清空。

5.此后每次Minor GC都会反复进行第3步和第4步的步骤。

6.当Survivor区域的对象年龄达到-XX:MaxTenuringThreshold设定值时(默认15),会将对象移入老年代。同时也清空它们在年轻代占用的内存空间。此处也会涉及到动态年龄判断

7.当老年代空间不够用了(此处会涉及到空间分配担保),会触发Full GC(回收所有堆内存)。

动态年龄判断

动态年龄判断。是对Survivor区的一种策略,是为了保证Survivor区具有充足的空间用于分配。动态对象年龄判断Survivor区是否存在“相等对象年龄的对象”超过Survivor from/to的内存空间的情况,直接将超过的对象放入老年代。

空间分配担保

空间分配担保。是对老年代的一种策略,是为了保证老年代有足够的空间,不至于OOM。在Minor GC实际发生前,JVM会判断之前连续几次年轻代中“Eden+Survivor区域将要晋升到老年代的对象”的平均大小是否大于老年代剩余空间的大小。

为什么要判断此前连续几次的年轻代晋升到老年代的平均大小?

因为实际上进入老年代的对象大小在GC前是未知的,这也是为什么采用之前晋升的平均值来进行判断担保,也就是说只是一种预测,并不能代表真实就是有这么多对象晋升

判断会出现以下两种情况:

1.如果大于,则说明老年代没有足够空间。则进行full GC(回收所有区域内存)。

2.若小于,说明老年代可能有足够空间。但还需要查看一个参数HandlePromotionFailure,即是否允许担保失败。如果允许担保失败,则Minor GC。

允许担保失败,进行Minor GC后会出现以下情况:

Minor GC之后的对象survivor区能够放下,直接结束GC;

Minor GC之后的对象survivor区放不下。进入到老年代,老年代能放下,结束GC;

Minor GC之后的对象survivor区放不下。进入到老年代,老年代也放不下。开始Full GC,然后再重新尝试放入老年代,如果老年代依然放不下,则报OOM(内存溢出)。

为什么Survivor有两个区域?

如果没有Survivor会怎样?

如果没有survivor,即意味着只有新生代和老年代,新生代在进行一次minor gc后存活的对象无处安放,只能升级到老年代中,这样老年代很快就会被装满,进行full gc。

这种情况下,要么增加老年代的大小,从而来降低Full GC的频率,这样做的缺点就是:由于老年代空间过大,Full GC的执行时间会变长,系统的响应性急剧下降;要么减小老年代的大小,Full GC消耗的时间变短,系统的响应性增强,但是Full GC发生的频率增多,系统的吞吐量下降。

如果只有一个Survivor会怎样?

如果刚开始survivor为空,新生代的对象都存放在Eden中,此时发生了一次minor gc 将Eden中存活的对象复制到survivor中,过了一段时间Eden满了,这时候无论是Eden中还是survivor中都存在需要被回收的对象,此时又发生了一次minor gc,则survivor中便出现了空间碎片。

如果试图将Eden区存活的对象转移到survivor中,努力适应这种不连续的空间。但是不连续的空间会导致再分配大对象的时候,由于没有连续的空间来分配,会导致提前垃圾回收。

如果将survivor中的所有存活对象向下移动来消除碎片,然后将所有的存活对象移入其中。这样做会降低效率。

两个Survivor

如果存在两个Survivor区。当Eden区满的时候,发生Minor GC:

  • Eden和Survivor0有存活对象,将对象转移到Survivor1中;
  • 当下次再发生Minor GC的时候,将Eden区和Survivor1区的存活对象复制到Survivor0中。

循环往复。直到存活对象old enough,升入老年代。这种情况下我们可以保证始终有一个Survivor的空间是没有碎片的,而另外一个Survivor是空着的。

参考文档

JVM 年轻代(Eden、From、To)、老年代讲解_°Fuhb的博客-CSDN博客_jvm年轻代和老年代概述JVM 的堆空间分成2个区域:年轻代、老年代年轻代又进一步细分成3个区域:Eden、Survivor From、Survivor To如下图所示:默认情况下,年轻代与老年代比例为1:2。可以通过参数-XX:NewRatio修改,NewRatio默认值是2。如果NewRatio修改成3,那么年轻代与老年代比例就是1:3默认情况下Eden、From、To的比例是8:1:1。可以通过参数-XX:SurvivorRatio修改,SurvivorRatio默认值是8,如果SurvivorRatio修https://blog.csdn.net/qq_28834355/article/details/116610058关于JVM中Eden区、Survivor from区和Survivor to区的理解_煲仔饭&流沙包的博客-CSDN博客_eden区与survivor区本文主要根据《深入理解JVM》中内存回收策略,主要关注如下五个方面:1:Eden区分配2:大对象直接进入老年代3:长期存活的对象直接进入老年代4:动态对象年龄判定5:空间分配担保 首先明确新生代都是分配于Eden区的,所以Eden区是最重要也是内存回收最重要的管理区域,同时也是最频繁的内存替换区域。我们知道JVM将内存根据分代策略将内存分为三层,新生代所占据的内存、老年...https://blog.csdn.net/qq_29631431/article/details/82344081?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-3-82344081-blog-116610058.pc_relevant_baidufeatures_v8&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-3-82344081-blog-116610058.pc_relevant_baidufeatures_v8&utm_relevant_index=6面试官:看你简历上写了熟悉JVM垃圾回收机制,那说说你了解的GC_局外人Inside的博客-CSDN博客目录1. 介绍一下垃圾回收机制:2. GC完整流程知道吗?介绍一下3. GC的四种算法有过了解吗?介绍一下4. 请介绍一下常用的几款垃圾回收器1. 介绍一下垃圾回收机制:当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(GenerationalCollection)的理论进行设计,分代收集名为理论,实质是一套符合大多 数程序运行实际情况的经验法则,它建立在两个分代假说之上: 1)弱分代假说(Weak Generational Hypo...https://blog.csdn.net/weixin_42189550/article/details/123377189JVM垃圾收集(三)— Appel式回收为什么使用两个Survivor_wxcperfect的博客-CSDN博客Appel式回收为什么使用两个Survivor一、Appel式回收Appel式回收的具体做法是把新生代分为一块较大的Eden空间和两块较小的 Survivor空间,每次分配内存只使用Eden和其中一块Survivor。发生垃圾搜集时,将Eden和Survivor中仍 然存活的对象一次性复制到另外一块Survivor空间上,然后直接清理掉Eden和已用过的那块Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1,也即每次新生代中可用内存空间为整个新 生代容量的90%(https://blog.csdn.net/Hello_mengkebao/article/details/119805735

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值