JVM有哪些垃圾回收器?是怎么工作的?什么是STW?它都发生在哪些阶段?什么是三色标记?如何解决错标记和漏标记的问题?为什么要设计这么多的垃圾回收器?
STW:Stop-The-Word。是在垃圾回收算法执行过程中,需要将JVM内存冻结的一种状态。在STW状态下java的所有线程都是停止执行的,GC线程除外。native方法可以执行(本地方法调用的底层C++的代码),但是不能与JVM交互。GC各种算法优化的重点就是减少STW,同时也是JVM调优的重点
JVM的垃圾回收器:
Serial串行:
整体过程比较简单,就像踢足球一样,需要GC时,直接暂停,GC完了再继续。这个垃圾回收器是比较早期的回收器,只有一个线程执行GC。在多CPU架构下,性能就会下降严重。只适用于几十兆的内存空间。
Parallel并行:
在串行基础上增加多线程GC ,PS(Parallel Scavenge)+PO(Parallel Old)这种组合是JDK1.8默认的垃圾回收器。在多CPU架构下性能会比Serial高很多。随着内存越来越大,多个GC线程还是不够忙活的,这时候提出了CMS回收器。
CMS:Concurrent Mark Sweep
核心思想就是将STW打散,让一部分GC线程与用户线程并发执行。整个GC过程分为4个阶段:
1.初始标记阶段:STW只标记出根对象直接引用的对象。
2.并发标记阶段:继续标记其他的对象,与应用程序是并发执行的。
3.重新标记阶段:STW对并发执行阶段的对象进行重新标记。
4.并发清除阶段:并行。将产生的垃圾清除。清除过程中,应用程序又会不断产生新的垃圾。叫浮动垃圾。这些垃圾就要留到下一个GC过程中清除。
CMS垃圾回收器是分代算法向不分代算法过度的一个过渡阶段
G1 Garbage First垃圾优先:
它的内存模型是实际上不分代逻辑上还是分代的,对于堆内存就不再分新生代和老年代,而是划分为一个一个的小内存块,叫做Region,每个Region隶属于不同的年代。
GC分为4个阶段:
1.初始标记:标记出GC Roots直接引用的对象。STW
2.标记Region:通过RSet标记出上一个阶段标记的Region引用到的Old区的Region。并发的,没有STW.
3.并发标记:跟CMS的步骤差不多的。只是遍历的范围不再是整个Old区,而只需要遍历第二步标记出来的Region
4.重新标记:跟CMS中的重新标记过程上差不多。
5.垃圾清理:与CMS不同的是,G1可以采用拷贝算法,直接将整个Region中的对象拷贝到另一个Region。而这个阶段,G1只选择垃圾较多的Region来清理,并不是完全清理。