垃圾回收器

面试官:你了解JVM的内存管理模型吗?

菜鸟:你指的是哪种垃圾回收器?

分代模型

年轻代的垃圾是容易被回收的垃圾,而老年代里是不容易被回收的垃圾。根据工业统计,年轻代的一次垃圾回收,就能回收接近90% 的垃圾。

JDK1,7还有永久代

年轻代使用的是Copying算法。

老年代使用的是Mark Compact 或者 Mark Sweep 算法

年轻代Copy过程:

第一次GC,eden里存活的对象被copy到 s1里,eden里剩余的全部被清除。

第二次GC,eden和s1里存活的对象copy到s2里,eden和s1里剩余的被清除。

死三次GC,eden和s2里存活的对象copy到s1里,eden和s2里剩余的被清除。

…………

依次循环。

有些对象实在无法被清除,到了一定年龄就会进入老年代。

年轻代与老年代的比例:1:2

eden与s1和s2的比例:8:1:1

垃圾回收器组合

分代模型里的垃圾回收器一定是成对出现的。

常见的有三种:

  1. ParNew + CMS
  2. Serial + Serial Old
  3. Parallel Scavenge + Parallel Old (1.8默认)

JDK1.8 可用分代模型,也可不用分代模型,可用G1。JDK1.9默认G1

Serial + Serial Old

现在很少使用了,是最早的垃圾回收器组合。

当有线程在工作时,突然有一个单线程的垃圾回收器来回收垃圾,所有工作的线程都有停止,等垃圾回收器工作完成以后,所有工作的线程才能恢复工作。所以在实际业务中,会出现卡顿的现象,很有可能是垃圾回收器在工作。

Parallel Scavenge + Parallel Old

当有线程在工作时,突然有一个多线程的垃圾回收器来回收垃圾,所有工作的线程都有停止,等垃圾回收器工作完成以后,所有工作的线程才能恢复工作。所以在实际业务中,会出现卡顿的现象,很有可能是垃圾回收器在工作。

Parallel Scavenge 与 Serial 的区别就是多线程和单线程

ParNew + CMS

因为Serial和Parallel Scavenge不能与CMS配对,为了与CMS配对,才有了ParNew。

CMS工作原理

初始标记:再根据根可达性算法标记垃圾的时候,此时并不会往下继续执行,而是只标记根对像就可以了,所以此处的停顿时间也是很少的,基本上也就是几百个毫秒,可以接收。

并发标记:垃圾回收线程与业务线程同时运行,在运行中如有业务线程产生了垃圾,会被垃圾回收吧线程直接标记为垃圾。但这里会有一些问题,如果一个对象被标记为垃圾后,又有其他对象指向了它,如果这个对象被当做垃圾处理会出问题,此时就会产生错标的问题。此处也有可能产生浮动垃圾,就是没有被标记的垃圾,但是没关系,等下次标记的时候再次处理。

重新标记:就是为了解决错标的问题。时间也和短。

并发清理:清理被标记的垃圾。此处也有可能产生浮动垃圾,没关系,等下次被标记为垃圾然后清除。

CMS错标对象修正的算法

三色标记算法

第一种情况:B—>D消失,增加 A—>D

正常情况

此时,垃圾回收器标记,标记完了,ABD都不是垃圾。

运行过程之中,B指向D的引用消失了,D成了浮动垃圾,等下次执行的时候会被标记为垃圾清理掉。

在B指向D的引用消失的与此同时,A增加了指向D的引用。因为A已经被标记为黑色了,(被标记为黑色是他的孩子都已经被标记过了,不会被重新标记),所以D,不会被找到,就会当做垃圾处理掉。

如何解决这个问题:

  • CMS解决方式

    Incremental Update

    就是把A变成灰色,就可以再次扫描标记了。

    会产生的问题:并发标记,产生漏标。

-------------本文结束感谢您的阅读-------------