Java应用启动的时候,除了配置Xms以及Xmx参数(Xmx:InitialHeapSize, Xms:MaxHeapSize),还须要选择合适的垃圾收集器。
截止Jdk1.8,共提供了7款垃圾收集器,每一款垃圾收集器都具备不一样的特色。咱们所须要作的就是,根据Java应用的特色已经部署环境,肯定不一样垃圾收集器的组合。这几款垃圾收集器之间联系以下图所示:
程序员
由上图可知,Serial,ParNew,Parallel Scavenge主要负责Young generation区域的垃圾回收,CMS,Serial Odl, Parallel Old主要负责Tenured generation区域的垃圾回收,G1在Young generation以及Tenured generation区域都可以使用(详细缘由在下文会进行阐述)。算法
jdk提供了多重垃圾收集器,下文会提供主流的垃圾收集器搭配组合,各类组合按照特色分为如下三类:微信
Serial收集器(Serial + Serial Old)的主要特色是单线程回收资源。当须要执行垃圾回收时,程序会暂停一切工做(又称为Stop The World,STW),使用复制算法完成垃圾清理工做。多线程
优势:并发
缺点:post
ParNew收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾收集工做,其余的控制参数,收集算法,对象分配规则等均与Serial收集器一致。
ParNew收集器在单核/双核环境下,效率未必有Serial收集器工做效率高(多线程切换开销等因素限制),固然随着核数的增长,其性能也会获得较大的提高。性能
Parallel收集器(Parallel Scavenge + Parallel Old)相比于Serial收集器的主要特色是,其是经过多线程完成垃圾的清理工做。其中Parallel Scavenge使用复制算法完成垃圾收集(Parallel Old使用标记整理算法),若是从这一点看其与ParNew类似,但实际上二者的出发点存在区别,区别以下所示:线程
高吞吐量适合于交互较少的后台应用程序(诸如科学计算应用),可以更加充分的压榨CPU。开发者能够根据应用的实际状况,经过调整如下两个参数追求最优性能:日志
CMS(Concurrent Mark Sweep)收集器是jdk 1.5推出的第一款真正意义上的并发收集器(针对老年代),实现了让垃圾收集器与用户线程(近似)同时工做,其具备如下特色:对象
CMS的垃圾收集过程比较复杂,主要步骤以下所示:
(1) CMS Initial Mark:初始标记Root(会STW,单线程执行,不过由于仅仅把GC Roots的直接可达对象标记一下,因此速度较快);
(2) CMS Concurrent Mark:并发标记;
(3) CMS Concurrent Preclean: 并发预清理;
(4) CMS Remark: 并发标记(会STW,此步骤是由于在并发标记的过程当中可能会产生新的垃圾,须要从新标记新产生的垃圾);
(5) CMS Concurrent Sweep: 并发清除;
(6) CMS Concurrent Reset: 并发重置。
以上步骤中,最为耗费时间的并发标记与并发清除阶段,不须要应用程序暂停执行,因此垃圾回收的停顿时间较短。
缺点:
针对以上缺点,能够从以下参数进行改进:
须要注意的是G1垃圾收集器在新生代以及老年代都能进行工做,这是由于相比于前面所介绍的垃圾收集器,它具备不一样的堆内存结构。之前的垃圾收集器分代是划分为新生代、老牛代、持久带等
。
G1将内存划分为多个大小相同的Region(1-32M,上限2048个),每一个Region均拥有本身的分代属性,这些分代不须要连续。经过划分Region,G1能够根据计算老年代对象的效益率,优先回收具备最高效益率的对象(分代的内存不连续,GC搜索垃圾时须要全盘扫描找出对象引用状况,G1经过在每一个Region中维护一个Remembered Set记录对象引用状况解决此问题)。具体以下图所示:
G1提供了两种GC模式,Young GC以及Mixed GC,两种GC都会STW。
选定全部年轻代里的Region。经过控制年轻代的region个数,即年轻代内存大小,来控制young GC的时间开销。
选定全部年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的若干老年代Region,在用户指定的开销目标范围内尽量选择收益高的老年代Region。
Mixed GC不是Full GC,它只能回收部分老年代的Region,若是mixed GC实在没法跟上程序分配内存的速度,致使老年代填满没法继续进行Mixed GC,就会使用serial old GC(full GC)来收集整个GC heap(此时效率就会很低下)。因此咱们能够知道,G1是不提供Full GC的。
在执行Mixed GC以前须要进行并发标记过程(Global Concurrent Marking),具体步骤以下图所示:
须要注意,Mixed GC并非一次性执行完,其会分为多个步骤执行(具体可见下一篇关于GC日志的文章)。在每次执行时,G1会计算每一个Region中垃圾占内存分段比例,若是超过了-XX:G1MixedGCLiveThresholdPercent,则进行回收操做。此外,G1中能够设置堆内存中有多少空间容许浪费,即-XX:G1HeapWastePercent,在并发标记结束后,能够知道有多少空间要被回收,在每次Young GC和发生Mixed GC以前,会检查垃圾占比是否到达了此阈值,只有到达了,才会发生Mixed GC。
PS:
资料收集过程当中,感谢如下做者文章的参考:
https://bdqfork.cn/articles/33
http://www.javashuo.com/article/p-gngwroki-km.html若是您以为个人文章对您有帮助,请关注个人微信公众号,谢谢!