GC相关问题

ps:以前看的好多书,都忘了,决定好好写博客,写总结了

GC的问题大致分为三大类:

  • 1.要gc哪些对象?

  • 2.通过什么方法来gc?

  • 3.什么时候触发gc?怎样gc的?

下面通过对这三个问题的思考来捋一捋gc相关的知识点:

一.要GC哪些对象?

通常来说,不使用的对象,就应该被回收,怎么找到不使用的对象呢?有两种算法:引用计数法,可达性分析法。对于java语言来说,由于循环引用的存在,因此引用计数法不可用。是通过可达性分析的方法去找到应该被回收的对象(不可达的对象)。
可达性分析:通过GCroots找到所有可达的对象,其余对象为不可达,并对其进行标记。但这一次标记的对象不一定全部被回收,如果实现了finialize()方法的对象会被放到F-quenu队列中,并执行finialize()自救,会对F-quenu中对象进行第二次标记,如果还是不可达,那么在GC的时候才会被回收。

二.通过什么方法来gc?

gc主要针对于jvm内存区的堆进行垃圾回收,对于垃圾回收的方法有三种主流算法:

  • 复制
  • 标记-清除
  • 标记-整理

复制算法,实现简单,效率高,但需要多一倍内存。
标记-清楚算法,实现简单,效率不高,且容易发生浮动垃圾,但不需要多一倍内存。
标记-整理算法,实现复杂,效率最低,但不回有浮动垃圾产生,也不需要多一倍内存

对于大多数对象来说,都是频繁的或者,频繁的死去,因此jvm采用分代的机制把堆分为了年轻代和老年代。年轻代采用复制算法,年老代采用(标记-清楚)或者(标记-整理),具体要看老年代的垃圾回收器。

三.什么时候GC?是怎样GC的?

3.1 什么时候GC?

jvm根据堆的划分,把gc大致分为了minorGc和fullGc,当然对于不同的垃圾回收器的实现还有不同的gc方式。
minorGc:
年轻代Gc,当Eden区满了后,就会发生minorGc,采用的是复制算法,把Eden区和S0区的剩余对象放到S1区中。这过程中有三个个细节:

1.如果一个对象在年轻代被GC的次数超过了设置的阀值,这个对象就会放到老年代中。
2.如果年轻代中相同年龄的对象大小的总和大于Survior区的一半,那么大于等于这个年龄的对象也会放到老年代中。
3.如果Eden区和from区剩余的对象存放到to区中,如果还有对象放不下剩余,这些对象就会加入到老年代。


对象进入老年代的四种情况:
    1.如果Eden区和from区剩余的对象存放到to区中,如果还有对象放不下剩余,这些对象就会加入到老年代。
    2.如果是大对象,直接放到老年代中。
    3.在新生代中,年龄超过设置阀值的对象会晋升到老年代。
    4.根据动态年龄判定,在新生代中有一半年龄超过某个值,那这一半都会晋升到老年代中

FullGc:整个堆和方法区进行Gc,有多个触发条件:

  • 1.显示调用System.gc()方法。
  • 2.minorGc后统计要晋升的对象大小大于老年代剩余的空间大小。就触发FullGc。
  • 3.在cms收集器并发清理阶段,也会产生垃圾,因此如果产生的垃圾,不能进入老年代,会触发concurrent-mode-failure 或者 晋升失败的情况,这时候会触发full gc
  • 4.方法区Perm空间不足。

除了minorGc和FullGc还有两种特殊的gc,cms垃圾回收器特有的oldgc 和 g1垃圾回收器特有的mixedGc。

oldGc:当老年代的对象数量多于cms设置的阀值,就触动oldGc,回收老年代中的对象,但是cms是基于并发-清除算法的,因此会产生很多浮动垃圾。当浮动垃圾过多时,导致触发fullGc,是调用SerialOld执行fullGc。


mixedGc:当g1垃圾收集器的全局并发标记的对象数量多于g1通过G1HeapWastePercent参数,在global
concurrent marking结束之后,我们可以知道old gen
regions中有多少空间要被回收,在每次YGC之后和再次发生Mixed
GC之前,会检查垃圾占比是否达到此参数,只有达到了,下次才会发生Mixed GC。

3.2 各个垃圾收集器是怎么GC的?

java中垃圾收集器分为3类:

  • 串行垃圾收集器:就是单线程的垃圾收集器Serial、SerialOld
  • 并行垃圾收集器:多个g1线程一起进行垃圾收集 ParallelScavenge、ParallelOld(优化吞吐量)
  • 并发垃圾收集器:CMS、G1 垃圾收集器(减少停顿时间)

这里并发是垃圾收集器线程和用户线程并发执行。即gc的过程中,用户线程并不是完全停止。

评判一个垃圾收集器的好坏的两个标准:

  • 停顿时间:垃圾收集器做垃圾回收中断应用程序执行的时间。
  • 吞吐量:垃圾回收的时间和花在应用程序的占比。

下面来重点介绍一下两个并发垃圾收集器:

简单说一下CMS和G1垃圾收集器

cms和g1 同样都是并发垃圾收集器,都可以在垃圾收集的过程中用户线程并发执行。
cms垃圾收集器是只作用在老年代的垃圾收集器,且其中的垃圾回收算法是采用标记-清除算法的。cms的gc过程是:

  • 初始标记 (stop the world)这次标记只标记和Gcroots直接关联的对象。
  • 并发标记 这次标记用户线程也在执行,gc线程标记gcroots路径上的对象。
  • 并发预清理 (这一步和重新标记是一样的,但是是并发的,此阶段标记从新生代晋升的对象、新分配到老年代的对象以及在并发阶段被修改了的对象,在这个阶段,可能会触发一次minorGC)
  • 重新标记 (stop the world)标记并发标记过程中,产生的新对象
  • 并发清除 用户线程和gc线程并发处理

由于cms采用的标记-清除算法,会产生大量的浮动垃圾,可能会导致“current-mode-failure”和晋升失败,触发Fullgc

g1垃圾收集器是作用在真个堆中的,这有别于其他所有的垃圾收集器,g1垃圾收集器虽然也有分代的概念,但实际上,它把内存分为多个region区域。
gc过程是:

  • 触发youngGc条件后,开始全局并发标记
  • 初始标记
  • 并发标记
  • 重新标记
  • 清楚垃圾

上面全局并发标记的步骤和cms基本一样,但是在重新标记后,会检查堆中垃圾是否达到G1HeapWastePercent设置的阀值,如果设置了,就开始mixedGc,否则只进行youngGc。
另外,一旦触发了fullgc,实际也是由serialOld执行fullgc。
从局部看,g1GC采用的是复制算法,从整体看采用的是标记-整理算法.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值