java垃圾回收算法不止一种,当然垃圾回收器也不止一种,本文主要介绍HotSpot虚拟机中的垃圾收集器。
定义:指的是使用单线程进行回收的回收器
特点:
A.每次回收时,串行回收器只有一个工作线程。
B.它是独占的垃圾回收(中间应用程序会停顿)。
C.实现相对简单,逻辑处理特别高效,没有线程切换的开销,使用的是复制算法。
使用:
"-XX:+UseSerialGC":添加该参数来显式的使用串行垃圾收集器;
和新生代串行回收器基本上一样,也是一种独占的,串行回收期。特点是会比新生代回收器占用更长的时间,使用的是压缩算法。
若要使用老年代串行回收器,可以尝试使用以下参数:
"-XX:+UseSerialGC":新生代和老年代都使用串行回收器
"-XX:+UseParNewGC":新生代使用ParNew回收器,老年代使用串行回收器;
"-XX:+UseParallelGC":新生代使用ParallelGC回收器,老年代使用串行回收器;
ParNew回收器是一个工作在新生代的垃圾回收器,它只是将简单的将串行回收多线程化,他的回收策略,算法,以及参数和新生代串行回收器一样。
使用场景:
在并发能力比较强的cpu上它的停顿时间要短与串行回收器,而在单cpu或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好,由于多线程的压力,它的实际表现可能比串行回收器差。 在Server模式下,ParNew收集器是一个非常重要的收集器,因为除Serial外,目前只有它能与CMS收集器配合工作;
使用:
"-XX:+UseConcMarkSweepGC":指定使用CMS后,会默认使用ParNew作为新生代收集器;
"-XX:+UseParNewGC":强制指定使用ParNew;
"-XX:ParallelGCThreads":指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同;
新生代的ParallelGC回收器表面上和ParNew回收器一样都是多线程,独占式的。它有一个很重要的特点就是,很关注吞吐量。
两个重要的调整参数
(A)、"-XX:MaxGCPauseMillis"
控制最大垃圾收集停顿时间,大于0的毫秒数;
MaxGCPauseMillis设置得稍小,停顿时间可能会缩短,但也可能会使得吞吐量下降;
因为可能导致垃圾收集发生得更频繁;
(B)、"-XX:GCTimeRatio"
设置垃圾收集时间占总时间的比率,0
垃圾收集执行时间占应用程序执行时间的比例的计算方法是:
1 / (1 + n)
例如,选项-XX:GCTimeRatio=19,设置了垃圾收集时间占总时间的5%--1/(1+19);
默认值是1%--1/(1+99),即n=99;
垃圾收集所花费的时间是年轻一代和老年代收集的总时间;
如果没有满足吞吐量目标,则增加代的内存大小以尽量增加用户程序运行的时间;
Parallel Old垃圾收集器是Parallel Scavenge收集器的老年代版本;
特点:
针对老年代;采用"标记-整理"算法;多线程收集;
使用:
"-XX:+UseParallelOldGC":指定使用Parallel Old收集器;
CMS:并发标记清理(Concurrent Mark Sweep),也称为并发低停顿收集器,CMS回收器主要关注于
系统停顿时间。使用标记清除算法,同时它又是一个使用多线程并行回收的垃圾回收器。
STW:表示Stop-the-world
橘色表示独占式的进程,其他过程和用户程序一起进行的。。。
特点:
基于"标记-清除"算法(不进行压缩操作,产生内存碎片);以获取最短回收停顿时间为目标;并发收集、低停顿;
CMS的三个缺点
(A)、对CPU资源非常敏感
CMS是多线程的,设置合理的工作线程数量对系统的性能有很重要的影响
CMS默认启动的并发线程数是(ParallelGCThreads+3)/4,ParallelGCThreads表示GC并行时使用的
线程数量。如果新生代使用ParNew(经常配合使用),那么ParallalGcThreads也就是新生代GC的线程数量。
并发线程数量可以通过-XX:ConcGCThreads或者-XX:ParallelCMSThreads手工设定,设置这个参数时
要小心,当CPU资源比较紧张的时候,受到CMS回收器线程的影响,应用程序的性能在垃圾回收阶段可能
会非常糟糕。
(B)、浮动垃圾
在并发清除时,用户线程新产生的垃圾,称为浮动垃圾;
CMS回收器不是独占式的,垃圾是不断产生的,CMS回收器不会等待堆满时才回收,当达到某个阀值 时就进行回收,
这个值通过"-XX:CMSInitiatingOccupancyFraction"设定
一般为68,表示当老年代空间使用率达到 68%时,就会执行一次CMS回收。
注意:如果内存增长缓慢,则可以设置一个稍大的值,大的阀值可以有效降低CMS的触发频率,减少老年代回收次数
可以明显改善应用程序的性能,反之,如果应用程序内存使用率增长很快,则应该降低这个阀值,以避免频繁
触发老年代串行收集器。
(C)、内存碎片
CMS基于标记清除算法实现,在垃圾回收时会产生大量的碎片,在即使堆内存中有较大的空间,而分配大的内存空间时
无法找到足够的连续内存,从而需要提前触发另一次Full GC动作。这样对系统的性能不利。
"-XX:+UseCMSCompactAtFullCollection"开关可以使CMS在垃圾收集完成之后,进行一次内存碎片整理,内存碎片的整理不是并发进行的。
"-XX:+CMSFullGCsBeforeCompaction"参数用于多少次CMS之后,进行一次内存压缩。
G1(GarbageFirst)垃圾收集器是当今垃圾回收技术最前沿的成果之一,同优秀的CMS垃圾回收器一样,G1也是关注最小时延的垃圾回收器,也同样适合大尺寸堆内存的垃圾收集,官方也推荐使用G1来代替选择CMS。G1最大的特点是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。在JDK1.7之后引入。
G1使用了全新的算法,特点如下:
并行性:G1在回收期间,可以由多个线程同时工作,有效利用多核的计算能力。
并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此一般来说
不会再整个回收期间完全阻塞应用程序。
分代GC:G1依然是一个分代收集器,但是和之前回收器不同,它同时兼顾年轻代和老年代。对比其他收集器只在年轻代或者老年代有很大不同。
空间整理:G1在回收过程中,会进行适当的对象移动,不像CMS只是简单地标记清理对象
在若干次GC后,CMS必须进行一次碎片的整理。而G1不同,它每次回收都会有效地复制对象,减少
空间碎片。
可预见性:由于分区的原因,G1可以只选取部分区域进行内存回收,这样输下了回收的范围,
因此对于全局停顿也能得到较好的控制。
设置相关的参数:
3、设置参数
"-XX:+UseG1GC":指定使用G1收集器;
"-XX:InitiatingHeapOccupancyPercent":当整个Java堆的占用率达到参数值时,开始并发标记阶段;默认为45;
"-XX:MaxGCPauseMillis":为G1设置暂停时间目标,默认值为200毫秒;
"-XX:G1HeapRegionSize":设置每个Region大小,范围1MB到32MB;目标是在最小Java堆时可以拥有约2048个Region;
【参考资料】
《深入理解Java虚拟机:JVM高级特性与最佳实践》
《实战java虚拟机》
这是结尾。。。