一.串行收集器
特点:最古老 最稳定 效率高
缺点:可能会发生较长时间的停顿
参数:-XX:+UseSerialGC
新生代.老生代使用穿行回收
老生代复制算法.新生代标记压缩算法
二.并行收集器
参数-XX:+UseParNewGC
影响:新生代串行.老年代并行(只影响新生代)
复制算法,因为是多线程的需要多核支持,多线程并行的复制算法
可以使用-XX:ParallelGCThreads限制线程数量
三.Parallel并行收集器
类似ParNew
新生代复制算法 老年代标记-压缩算法
-XX:+UseParallelGC使用Parallel收集器+老年代串行
-XX:+UseParallelOldGC使用Parallel收集器+并行老年代
四.常用参数
参数-XX:PretenureSizeThreshold
使用-XX:PretenureSizeThreshold=100000000 单位byte 当大于这个值的时候直接在老年代创建内存 以免在新生代浪费内存复制浪费时间GC.
参数-XX:SurvivorRatio=8 eden区和幸存代占比是8:1
年龄判断
参数-XX:MaxTenuringThreshold=15 JVM给每个对象设置了一个年龄(Age)计数器,每个对象在Eden区出生并经历过第一次MinorGC后仍然存活,并且被survivor所接纳的话 那么他的年龄就增加1岁,当他的年龄增加到一定的程度(默认是15岁)就会被晋升到老年代.当然关于这个岁数的阈值可以通过参数调整的---来自<<深入理解Java虚拟机>>
动态年龄判断
为了能更好的适应不同程序的内存状况,虚拟机并不是永远的要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在survivor空间中相同的年龄所有对象大小的总和大于survivor空间的一半,那么年龄大于或者等于该年龄的对象就直接晋级老年代了.---来自<<深入理解Java虚拟机>>
分配担保策略
在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlerPromotionFailure设置是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小。如果大于,将尝试着进行一次Monitor GC,尽管这次GC是有风险的。如果小于,或者HandlerPromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC了。
上述所说的冒险到底是冒的什么险呢?
前面提到过,新生代使用复制收集算法,但是为了内存利用率。只使用其中一个Survivor空间来作为轮换备份,因此当出现大量对象在Minor GC后仍然存活的情况(最极端的情况是内存回收之后,新生代中所有的对象都存活),就需要老年代进行分配担保,把Survivor无法容纳的对象直接进入老年代。老年代要进行这样的担保,前提是老年代本身还有容纳这些对象的剩余空间,一共有多少对象存活下来在实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均大小值作为经验值,与老年代的剩余空间进行比较,决定是否进行Full GC来让老年代腾出更多空间。
取平均值进行比较其实仍然是一种动态概率的手段,也就是说,如果某次Minor GC存活后的对象突增,远远高于平均值的话,依然会导致担保失败。如果出现HandlerPromotionFailure失败,那就只好在失败后重新发起一次FULL GC。虽然担保失败时绕的圈子是最大的,但大部分情况下都还是将HandlerPromotionFailure开关打开,避免Full GC过于频繁。---来自<<深入理解Java虚拟机>>