hotspot的GC算法经历了很多个版本发展,在不同阶段也使用了不同的算法,这里仅仅描述了现在主流的hotspot版本(1.6)中常用的GC算法配置方法和表象,对算法的细节不进行描述。
-XX:+UseSerialGC
串行垃圾搜集算法,具体表现为:
新生代:
[DefNew: 34944K->3031K(39296K), 0.0264555 secs] 34944K->3031K(126720K), 0.0265033 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
老年代:
[GC [DefNew: 37824K->37824K(39296K), 0.0000274 secs][Tenured: 84770K->87423K(87424K), 0.6707186 secs] 122594K->90531K(126720K), [Perm : 2963K->2963K(12288K)], 0.6708503 secs] [Times: user=0.67 sys=0.00, real=0.67 secs]
Full:
[Full GC [Tenured: 87423K->87423K(87424K), 0.9254085 secs] 126719K->106207K(126720K), [Perm : 2962K->2962K(12288K)], 0.9254837 secs] [Times: user=0.92 sys=0.00, real=0.92 secs]
-XX:+UseParallelGC
并行垃圾搜集算法,新生代使用并行,老年代使用Mark-Sweep-Compact(标记,清除,压缩)
新生代:
[GC [PSYoungGen: 35680K->5432K(38208K)] 35680K->5636K(125632K), 0.0153779 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
full:
[Full GC [PSYoungGen: 32768K->7374K(38080K)] [PSOldGen: 87423K->87423K(87424K)] 120191K->94798K(125504K) [PSPermGen: 2963K->2963K(12288K)], 0.4979593 secs] [Times: user=0.50 sys=0.00, real=0.50 secs]
-XX:+UseParallelOldGC
并行垃圾搜集,老年代和新生代都是并行垃圾搜集
新生代:
[GC [PSYoungGen: 27552K->2144K(34432K)] 74201K->50809K(121856K), 0.0170400 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]
full:
[Full GC [PSYoungGen: 32768K->18745K(38080K)] [ParOldGen: 87423K->87423K(87424K)] 120191K->106169K(125504K) [PSPermGen: 2962K->2962K(12288K)], 0.9138238 secs] [Times: user=3.13 sys=0.00, real=0.92 secs]
-XX:+UseConcMarkSweepGC
标记清除算法,每次只清除一部分死亡对象,基本不会造成stop the world,但是会有内存碎片可以配合以下选项来对碎片问题进行优化:
-XX:+UseCMSCompactAtFullCollection:让full gc的时候,顺便对内存进行整理
-XX:+CMSFullGCsBeforeCompact: 多少次full gc后,再执行full gc时就进行内存整理
从算法行为上来说有4种类型:
- Mark-sweep:标记清除,缺点是会有大量内存碎片
- 复制算法(copying):简单高效,把存货的对象从一个区域复制到另一个区域,但是在存活率较高的情况下效率会变低(某个对象总是存活,那么自然就要来回复制,如果这些对象生命周期都很短,那么在GC的时候直接就不用复制到另一个区域了)
- 标记整理(Mark-compact):同标记清除类似,但是后续操作不是清除死亡的对象,而是把所有存活的对象往内存一边移动,将另外以便的内存所有都清理掉。
- 分代搜集(具体到每一代又采用了上述三种算法)。