典型的垃圾收集器
如果说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现。Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大的差别,并且一般都会提供参数共用户根据自己的应用特点和需求组合出各个年代所使用的收集器
1.Serial收集器
Serial收集器是最基本最古老的收集器,它是一个单线程收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是它进行垃圾收集时,必须暂停其他所有的工作线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。
它的优点是实现简单高效,但是缺点是会给用户带来停顿。
它最适合简单的命令行程序。通过-XX:+UseSerialGC
参数来选用Serial Garbage Collector。
2.Serial Old收集器
单线程收集器,针对老年代的收集器,采用标记-整理算法。
作为CMS收集器的后备收集器:当CMS收集器产生Concurrent Mode Failure时,将临时启动Serial Old收集器重新进行老年代的垃圾收集
3.ParNew收集器
ParNew收集器是Serial收集器的多线程版本,新生代收集器使用复制算法.除了使用多线程进行垃圾收集外,其余行为与Serial收集器完全一样,依然会stop the world很多虚拟机-server模式下的首选新生代收集器,主要原因是CMS收集器(老年代收集器)只能与Serial收集器或者ParNew收集器配合使用默认开启的回收线程数与CPU个数相同(现代服务器动辄32个逻辑CPU将会导致ParNew收集器开启32个收集线程,这种情况下最好限制下收集线程个数)
-XX:ParallelGCThreads 多线程垃圾收集器内存回收开启的线程数量
4.Parallel Old收集器
Parallel Old是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。
5.Parallel Scavenge收集器
Parallel Scavenge收集器是一个新生代的多线程收集器(并行收集器),采用的是Copying算法,它在回收期间不需要暂停其他用户线程.该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。吞吐量=运行用户代码时间/(运行用户代码时间+垃圾回收时间)
停顿时间短则响应速度快,适合与用户交互比较多的应用;吞吐量大能够最高效的利用CPU时间,尽快完成运算任务,适合后台运算、交互不多的应用.
GC拥有自适应调节策略。如果启用该策略,只需要设置好基本参数(-Xmx等),然后设置一个优化目标(最大垃圾收集时间或吞吐量大小),虚拟机会根据当前系统的运行状况收集性能监控信息,动态调整细节参数设置。
-XX:MaxGCPauseMillis 最大停顿时间,仅对Parallel Scavenge收集器生效
-XX:GCTimeRatio 吞吐量大小,默认值为99,即1%的GC时间,仅对Parallel Scavenge收集器生效
-XX:+UseAdaptiveSizePolicy 使用GC自适应调节策略
6.CMS收集器
用多个线程来扫描堆内存来标记需要回收的实例,然后再清除被标记的实例。CMS Garbage Collector只有在如下两种情景才会暂停所有的应用线程:
1.当标记永久代内存空间中的对象时;
2.当进行垃圾回收时,堆内存同步发生了一些变化。
相比Parallel Garbage Collector,CMS Garbage Collector使用更多的CPU资源来确保应用有一个更好的吞吐量。如果分配更多的CPU资源可以获得更好的性能,那么CMS Garbage Collector是一个更好的选择,相比Parallel Garbage Collector。
通过XX:+USeParNewGC
参数来选用CMS Garbage Collector。
该收集器的收集过程分为4个步骤:
1.初始标记 CMS initial mark:该步会stop the world,但耗时非常短,标记GC Root直接关联的对象
2.并发标记 CMS concurrent mark:耗时较长,用户线程可同时运行,标记至GC Root有可达路径的对象
3.重新标记 CMS remark:该步会stop the world,但耗时非常短。由于步骤2用户线程同步运行,此时主要修正因步骤二同步用户线程产生的对象标记变动
4.并发清除 CMS concurrent sweep:耗时较长,用户线程可同时运行
在耗时很长的并发标记阶段和并发清除阶段用户线程和收集线程都可同时工作,故而总体上来说,CMS收集器的内存回收是与用户线程一起并发执行的.虽然收集停顿时间短,但是也有不少缺点:
1.对CPU资源敏感,CMS收集器默认开启的收集线程数为(CPU数量+3)/4,如果CPU数量较少,会占用不少CPU处理资源
2.无法处理浮动垃圾,并且可能产生Concurrent Mode Failure从而导致另一次Full GC。
并发清除时(步骤4),用户线程是可以同时运行的,此时用户线程会产生新的垃圾,这部分垃圾在标记过程之后产生,本次GC已经不能进行标记后清除,只能留到下次GC时处理,被称为浮动垃圾
由于CMS的收集线程执行时,用户线程也是会同时执行的,导致CMS收集器无法像其它老年代收集器那样在老年代内存几乎耗尽时在进行GC,必须为用户线程预留部分内存(默认使用68%内存就会开启收集过程),如果预留内存无法满足用户线程的执行,将会出现Concurrent Mode Failure,此时虚拟机将会启动备用方案,调用Serial Old收集器执行一次Full GC,这将导致较长的收集停顿
-XX:CMSInitiationgOccupancyFraction 设置GC触发的百分比,默认为68%,太高会导致过多的Concurrent Mode Failure,太低则影响性能,仅对CMS收集器生效
3.由于采用标记-清除算法实现,会产生内存碎片
-XX:+UseCMSCompactAtFullCollection Full GC后提供内存整理,该过程是无法并发的,会导致性能下降,仅对CMS收集器生效
-XX:+CMSFullGCsBeforeCompation 设置进行完几次不进行压缩的Full GC后,进行一次附带压缩的Full GC,仅对CMS收集器生效
7.G1收集器
G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。
用于大的堆内存区域。它将堆内存分割成多个独立区域(Region),然后并发地对它们进行垃圾回收。在释放内存后,G1还可以压缩空闲的堆内存。但是,CMS Garbage Collector是通过“Stop The World (STW)”来进行内存压缩的。G1优先收集可回收更多内存的区域。
通过–XX:+UseG1GC
参数来选用G1 Garbage Collector。
附:收集器的组合使用:
-XX:+UseSerialGC 使用Serial+Serial Old的收集器组合
-XX:+UseParNewGC 使用ParNew+Serial Old的收集器组合
-XX:+UseConcMarkSweepGC 使用ParNew+CMS(Serial Old)的收集器组合
-XX:+UseParallelGC 使用Parallel Scavenge+Serial Old的收集器组合
-XX:+UseParallelOldGC 使用Parallel Scavenge+Parallel Old的收集器组合