收集器设置
Java堆内存被划分为新生代和年老代两部分,新生代主要使用复制和标记-清除垃圾回收算法,年老代主要使用标记-整理垃圾回收算法,因此java虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器,JDK1.6中Sun HotSpot虚拟机的垃圾收集器如下:
图中如果两个垃圾收集器直接有连线,则表明这两个垃圾收集器可以搭配使用。
年轻代
串行收集器:-XX:+UseSerialGC 采用复制算法,Serial垃圾收集器依然是java虚拟机运行在Client模式下默认的新生代垃圾收集器。
并行收集器:-XX:+UseParNewGC 采用复制算法,打开此开关参数后,使用ParNew+Serial Old收集器组合进行垃圾收集。ParNew收集器默认开启和CPU数目相同的线程数,可以通过-XX:ParallelGCThreads参数来限制垃圾收集器的线程数。
并行收集器(吞吐量优先)-XX:+UseParallelGC 采用复制算法,提供一个参数:-XX:+UseAdaptiveSizePolicy,动态配置年轻代大小。
年老代
串行Serial Old收集器:通过配置新生代的参数配置,使用标记-整理算法,这个收集器也主要是运行在Client默认的java虚拟机默认的年老代垃圾收集器。在Server模式下,主要有两个用途:
a.在JDK1.5之前版本中与新生代的Parallel Scavenge收集器搭配使用。
b.作为年老代中使用CMS收集器的后备垃圾收集方案?
并行Parallel Old收集器(吞吐量优先):-XX:+UseParallelOldGC:,Parallel Old收集器是Parallel Scavenge的年老代版本,使用多线程的标记-整理算法,在JDK1.6才开始提供。
并发Concurrent mark sweep(CMS)收集器:-XX:+UseConcMarkSweepGC,其最主要目标是获取最短垃圾回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。
年轻代和年老代将根据默认的比例(1:2)分配堆内存
- 更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间;小的年老代会导致更频繁的Full GC
- 更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短;大的年老代会减少Full GC的频率
系统默认收集器
默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前系统配置进行判断。
client模式
年轻代使用Serial垃圾收集器,年老代使用Serial Old收集器,都是串行收集器。
server模式
年轻代使用ParNew垃圾收集器,年老代使用Serial Old收集器。
GC简单介绍
普通GC(minor/Scavenge GC):只针对新生代区域的GC
全局GC(Full GC):针对所有分代区域(新生代、年老代、永久代)的GC
触发FULL GC条件:
1.system.gc();
2.旧生代空间不足
3. Permanet Generation空间满
4. CMS GC时出现promotion failed和concurrent mode failure
promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。
5.统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间。 在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。
收集规则举例:
规则一:通常情况下,对象在eden中分配。当eden无法分配时,触发一次Minor GC。
规则二:配置了PretenureSizeThreshold的情况下,对象大于设置值将直接在老年代分配。
规则三:在eden经过GC后存活,并且survivor能容纳的对象,将移动到survivor空间内,如果对象在survivor中继续熬过若干次回收(默认为15次)将会被移动到老年代中。回收次数由MaxTenuringThreshold设置。
规则四:如果在survivor空间中相同年龄所有对象大小的累计值大于survivor空间的一半,大于或等于个年龄的对象就可以直接进入老年代,无需达到MaxTenuringThreshold中要求的年龄。
规则五:在Minor GC触发时,会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间,如果大于,改为直接进行一次Full GC,如果小于则查看HandlePromotionFailure设置看看是否允许担保失败,如果允许,那仍然进行Minor GC,如果不允许,则也要改为进行一次Full GC。