HotSpot虚拟机GC简单总结

4 篇文章 0 订阅

具体的GC相关文章网络上很多,这里不去重复。本文简要总结GC算法和回收器。

一、GC算法

1、标记-清除
给对象做标记,进行标记后每个对象对应一个状态,死亡、存活。标记完成后将标记为死亡的对象清除。
2、标记-整理
和标记-清除相比多一个步骤,将标记为死亡的对象清除后,还要将存活的对象整理到一起(逻辑空间连续)。
3、复制
空间被分成两个部分,只使用其中一个部分进行对象分配。当用来存储新对象的空间满了之后,将存活对象复制到另一个内存空间中,然后将之前的内存空间清空。
4、分代收集
内存空间被分为新生代和老年代。对新生代采用复制算法,对老年代采用标记-整理或者标记-清除算法。

二、为什么会有这么多GC算法

首先,为了区分存活对象和死亡对象,要做标记。问题在于对象被清除后,其占用的内存被释放出来。我们知道,如果产生很多内存碎片的话,对内存的使用效率就会大打折扣。

  • 所以在GC之后的内存使用率上,标记-整理、复制都有对存活对象内存的整理工作,它们在内存使用率上要高于标记-清除算法。
  • 标记-整理和复制的区别主要在于复制算法用了两个内存区域,每次执行将存活对象从一个区域到另一个内存区域的复制。但是无论是整理还是复制,都要对活对象进行复制转移操作,如果对象非常多,那转移的代价就有些大,因而出现了目前比较主流的分代收集。
  • 分代收集是从对象的存活率上来考虑的,因为新生代上的大量对象生存周期短,每次触发GC时,新生代都有大量的死亡对象,而存活对象较少,于是这部分采用复制算法,复制转移工作量就会小很多,反映在停顿上就少许多,响应效果就好一些。而对于老年代,由于其对象存活率高,复制转移的工作量可能很大,所以使用标记-清除算法。(注:CMS使用标记-清除,其目标是整个老年代,G1使用标记-整理,其目标是有限个region)。

三、垃圾收集器

垃圾收集器的目标:兼顾响应(停顿时间尽可能短)与吞吐率(GC越频繁,吞吐率越低)
串行收集器:工作时stop-the-world,单线程收集
并行收集器:多线程并行收集

下图展示了HotSpot虚拟机的垃圾收集器
在这里插入图片描述

1、Serial收集器
收集时暂停应用程序。新生代采用复制算法,老年代采用标记-压缩算法。收集过程单线程执行。
2、ParNew
收集时暂停应用程序。新生代采用复制算法,多线程并行收集。ParNew只针对新生代(从其名称中的New也可以看出来),老年代采用标记-压缩算法。
3、Parallel scavenge
-XX:+UseParallelGC
收集时暂停应用程序。新生代采用复制算法,多线程并行收集。老年代采用标记-压缩算法,单线程收集。
-XX:+UseParallelOldGC
收集时暂停应用程序。新生代采用复制算法,多线程并行收集。老年代采用标记-压缩算法,多线程并行收集。比较好记,Parallel表示并行的意思,加了Old表示也对老年代并行收集。
4、CMS(Concurrent Mark Sweep 并发标记清除)
-XX:+UseConcMarkSweepGC

注:CMS用于老年代垃圾收集,年轻代使用ParNew收集器。年轻代和老年代垃圾回收各自独立。

初始标记:应用程序暂停,标记根可直接关联的对象,然后恢复应用程序;
并发标记:沿着GC roots搜索引用链,对所有对象做可达性标记。此过程和应用程序并发执行;
并发标记的过程在官网中1.8版本的描述中还有下边一段:Concurrently retrace sections of the object graph that were modified since the tracing in the previous step, using one processor. 这一过程的合理的解释应该是在并发标记过程中,和应用程序并发执行,这一过程可能会产生新的对象进入到老年代。所以,在并发标记的后半段,也存在一个并发重标记的过程。又因为重标记会暂停,所以这一步应该是为减少重标记的工作量。
重标记:应用程序暂停,对之前的标记再做修正,因为暂停之前依然可能有新对象进入到老年代。
并发清理:和应用程序并发执行,清除不可达对象。
并发重置:和应用程序并发执行,重置CMS垃圾收集器的数据结构,为下一次垃圾回收做准备。
5、G1
要点:
(1)G1收集器将整个heap区域划分成相等的region大小,eden、survivor、old generation是不同的region组成的不同逻辑集合,不连续;
(2)并发全局标记整个heap以确定各region对象存活率;
(3)使用耗时预测模型来确定在用户指定的停顿时间内回收哪些region,回收多少。

标记过程
初始标记阶段:这一过程在G1 GC在年轻代收集时(因此有应用程序暂停)捎带进行。这一阶段标记GC roots。
Root region scanning阶段:扫描初始标记阶段幸存的survivor regions,标记region中有引用关系(被老年代中的对象引用)的在老年代中的对象。这一过程和应用程序并发执行,没有停顿。必须在下一次年轻代GC开始之前完成(因为年轻代GC又会有新的初始标记)。
并发标记阶段:并发标记整个堆所有region中的可达对象,和应用程序并发执行。这一过程可被年轻代GC打断(这一阶段产生新的对象没有关系)。
重标记阶段:暂停应用程序,对并发标记阶段发生的变化进行修正,以完成标记。使用初始快照算法SATB(snapshot-at-the-beginning)将存活对象记录在buffer中。
清理阶段:暂停应用程序,多线程并行执行,将heap上的一个或者多个region的存活对象拷贝到单个region上并紧凑排列以释放内存,清理region并重置RSet 、CSet,并将清空的region返回给free list。(这里涉及的两个数据结构,CSet:Collection Set 对应于region RSet:Remember Set 对应于region中的对象引用,表示外部对象对该region中对象引用的记录,各region的RSet相互独立,这就避免了回收region时要扫描整个heap)。

参考文章如下:
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/
https://www.cnblogs.com/jobbible/p/9800222.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值