如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。
JVM无非就是按照上篇文章的算法去做实现
文章在这里
CSDNhttps://mp.csdn.net/mp_blog/creation/editor/122898005
下面讲述本人对JVM实现的集中垃圾收集器的个人理解,如有其他见解,欢迎讨论
1:Serial收集器-XX:+UseSerialGC-XX:+UseSerialOldGC
新生代采用复制算法,老年代采用标记-整理算法
单线程收集器,gc时会暂停应用所有线程,起一个线程去收集,收集完成后,恢复其他线程
采用了分代收集,新生代采用复制算法,老年代采用标记-整理算法
优点:简单,单线程没有线程开销,效率高
缺点:收集是要暂停应用其他线程,会带来用户体验影响
2:Parallel Scavenge收集器-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代)
新生代采用复制算法,老年代采用标记-整理算法
Parallel收集器其实就是Serial收集器的多线程版本,其余行为和Serial收集器类似,可以使用
(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改
优点:cpu资源利用率高,相比Serial单线程在暂停其他线程的时间减少。提高了用户体验
缺点:增加了线程开销,不过相对用户体验提升来说,这都不算什么
3:ParNew收集器-XX:+UseParNewGC
新生代采用复制算法,老年代采用标记-整理算法
ParNew收集器其实跟Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用。
CMS收集器-XX:+UseConcMarkSweepGC(old)
CMS 收集器是一种真正的并发收集器,最大程度上缩短了用户应用线程暂停的时间,基本上实现了垃圾 收集线程和用户线程同时工作
CMS收集器是一种“标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:
初始标记:暂停所有的其他线程,并记录下gcroots直接能引用的对象,速度很快。
并发标记:并发标记阶段就是从GCRoots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变
重新标记:重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。
并发清理:开启用户线程,同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理
并发重置:重置本次GC过程中的标记数据
流量大,并发大的最优方案
ParNew+CMS
还有其他垃圾收集器,后续在写