以前一篇Blog已经将GC的机制以及GC的算法讲了一下。 html
而这篇Blog主要是讨论这些GC的算法在JVM中的不一样应用。 java
串行收集器是最古老,最稳定以及效率高的收集器
可能会产生较长的停顿,只使用一个线程去回收
-XX:+UseSerialGC 算法
0.844: [GC 0.844: [DefNew: 17472K->2176K(19648K), 0.0188339 secs] 17472K->2375K(63360K), 0.0189186 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 8.259: [Full GC 8.259: [Tenured: 43711K->40302K(43712K), 0.2960477 secs] 63350K->40302K(63360K), [Perm : 17836K->17836K(32768K)], 0.2961554 secs] [Times: user=0.28 sys=0.02, real=0.30 secs]
-XX:+UseParNewGC(new表明新生代,因此适用于新生代) 安全
Serial收集器新生代的并行版本
在新生代回收时使用复制算法
多线程,须要多核支持
-XX:ParallelGCThreads 限制线程数量 多线程
并行收集器的日志输出: 并发
0.834: [GC 0.834: [ParNew: 13184K->1600K(14784K), 0.0092203 secs] 13184K->1921K(63936K), 0.0093401 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1.500: [Full GC [PSYoungGen: 2682K->0K(19136K)] [ParOldGen: 28035K->30437K(43712K)] 30717K->30437K(62848K) [PSPermGen: 10943K->10928K(32768K)], 0.2902791 secs] [Times: user=1.44 sys=0.03, real=0.30 secs]
-XX:MaxGCPauseMills
布局
1. 初始标记(会产生全局停顿)
性能
CMS收集器的日志输出: spa
1.662: [GC [1 CMS-initial-mark: 28122K(49152K)] 29959K(63936K), 0.0046877 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.666: [CMS-concurrent-mark-start] 1.699: [CMS-concurrent-mark: 0.033/0.033 secs] [Times: user=0.25 sys=0.00, real=0.03 secs] 1.699: [CMS-concurrent-preclean-start] 1.700: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.700: [GC[YG occupancy: 1837 K (14784 K)]1.700: [Rescan (parallel) , 0.0009330 secs]1.701: [weak refs processing, 0.0000180 secs] [1 CMS-remark: 28122K(49152K)] 29959K(63936K), 0.0010248 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.702: [CMS-concurrent-sweep-start] 1.739: [CMS-concurrent-sweep: 0.035/0.037 secs] [Times: user=0.11 sys=0.02, real=0.05 secs] 1.739: [CMS-concurrent-reset-start] 1.741: [CMS-concurrent-reset: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]CMS收集器特色:
尽量下降停顿
会影响系统总体吞吐量和性能
.net
33.348: [Full GC 33.348: [CMS33.357: [CMS-concurrent-sweep: 0.035/0.036 secs] [Times: user=0.11 sys=0.03, real=0.03 secs] (concurrent mode failure): 47066K->39901K(49152K), 0.3896802 secs] 60771K->39901K(63936K), [CMS Perm : 22529K->22529K(32768K)], 0.3897989 secs] [Times: user=0.39 sys=0.00, real=0.39 secs]一旦 concurrent mode failure产生,将使用串行收集器做为后备。
CMS也提供了整理碎片的参数:
-XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理
G1是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是将来能够替换掉JDK1.5中发布的CMS收集器。
与CMS收集器相比G1收集器有如下特色:
1. 空间整合,G1收集器采用标记整理算法,不会产生内存空间碎片。分配大对象时不会由于没法找到连续空间而提早触发下一次GC。
2. 可预测停顿,这是G1的另外一大优点,下降停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能创建可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片断内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已是实时Java(RTSJ)的垃圾收集器的特征了。
上面提到的垃圾收集器,收集的范围都是整个新生代或者老年代,而G1再也不是这样。使用G1收集器时,Java堆的内存布局与其余收集器有很大差异,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔阂了,它们都是一部分(能够不连续)Region的集合。
G1的新生代收集跟ParNew相似,当新生代占用达到必定比例的时候,开始出发收集。
和CMS相似,G1收集器收集老年代对象会有短暂停顿。
步骤:
GC的停顿主要来源于可达性分析上,程序执行时并不是在全部地方都能停顿下来开始GC,只有在到达安全点时才能暂停。
安全点的选定基本上是以程序“是否具备让程序长时间执行的特征”为标准进行选定的——由于每条指令执行的时间都很是短暂,程序不太可能由于指令流长度太长这个缘由而过长时间运行,“长时间执行”的最明显特征就是指令序列复用,例如方法调用、循环跳转、异常跳转等,因此具备这些功能的指令才会产生安全点。
接下来的问题就在于,如何让程序在须要GC时都跑到安全点上停顿下来,大多数JVM的实现都是采用主动式中断的思想。
主动式中断的思想是当GC须要中断线程的时候,不直接对线程操做,仅仅简单地设置一个标志,各个线程执行时主动去轮询这个标志,发现中断标志为真时就本身中断挂起,轮询标志的地方和安全点是重合的,另外再加上建立对象须要分配内存的地方。
只要记住流行的组合就这几种状况
Serial
ParNew + CMS
ParallelYoung + ParallelOld
G1GC
2. http://www.importnew.com/15311.html
3. http://www.zhihu.com/question/30538696