12.GC汇总

GC总结

Minor GC Major GC FullGC

  • Minor GC 新生代GC
  • Major GC 老年代GC
  • Full GC 整堆收集,收集整个java堆和方法区的所有垃圾

因为STW问题的存在,尽量避免垃圾回收

Major GC 和Full GC出现STW的时间往往是Minor GC的10倍以上 所以尽量避免出现Major GC和Full GC的调用

  • JVM在进行GC时,并非每次都对上面三个内存区域一起回收,大部门时间回收是在新生代.针对HotSpot虚拟机,他里面的GC按照回收区域又分为两大类型
    • 部分收集Partial GC

不收集整个Java堆空间

新生代的收集 Minor GC /Young GC 只是新生代的垃圾收集

老年代的收集 Major GC / Old GC 只是老年代的垃圾收集

  • 目前只有CMSGC会有单独收集老年代的行为
  • 注意很多时间Major GC会和Full GC混淆,需要具体分辨是老年代回收还是整堆回收

混合收集 Mixed GC 整个新生代和部分老年代的垃圾手机

  • 目前只有G1 GC会有只有行为
  • 整堆收集 Full GC 整个java堆和方法区的垃圾收集

Minor GC

  1. 当新生代空间不足,会触发MinorGC,这里新生代具体只的是Eden满,Survivor满不会触发GC
  2. 因为java对象大多数具备朝生夕死的特性,所以Minor GC会非常的频繁,一般回收的速度也比较快
  3. Minor GC也会引发STW 暂停其他用户进程,等垃圾回收结束,用户线程才恢复运行
  4. image-20200707095606813

Major GC

  • 指发生在老年代的GC,对象从老年代消失时,我们说Major GC 或者 Full GC发生了
  • 出现MajorGC 通常至少会有一次Minor GC (但非绝对,在Parallel Scavenge收集器的收集策略里面有直接进行MajorGC的策略选择过程)
  • 在老年代空间不足的时候会先尝试MinorGC,如果之后空间还不足,触发Major GC
  • Major GC的速度比Minor GC慢10倍以上,STW时间更大,如果Major GC之后内存还不足就触发OOM

Full GC

  • 触发Full GC的情况有五种
    1. 显示调用System.gc() 系统建议执行FullGC,但不一定执行
    2. 老年代空间不足
    3. 方法区空间不足
    4. 通过Minor GC后进入老年代的平均大小 大于老年代的可用内存
    5. 由Eden Survivor Space(From) 向Survivor Space (To)复制时,对象大小大于To的可用内存,则把该对象转存到老年代,但此时老年代的内存小于该对象大小

图解

public class HeapTest3 {
    public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "mogu blog";
            while(true) {
                list.add(a);
                a = a + a;
                i++;
            }
        }catch (Exception e) {
            e.getStackTrace();
        }
    }
}

在这里插入图片描述

  • 第一次Eden满之后触发GC 向数据流向Survivor TO 和Old区
  • 第二次Eden满 触发Minor GC与上次操作相同
  • 经历2次GC之后老年代满了触发了一次FullGC,清空了新生代的数据,对Old区的数据进行清理
  • 第三次Major GC尝试处理,但此时因为字符串过长新生代已经无法存下了.直接尝试放入Old区
  • 第二次Full GC Old区已经放不下了触发FullGC之后发现还是放不下抛出OOM异常

堆空间分代思想

为什么要把java堆分带?不分带就不能正常工作?经研究,不同对象的生命周期不同.70%-99%的对象都是临时对象.

新生代: 有Eden和两块大小相同的Survivor (FROM/TO) TO总为空

老年代: 存在新生代经理多次GC仍然存活的对象

image-20200707101511025image-20200707101543871

  • 也可以不分带,分带的唯一目的就是优化GC的性能,尽量减少GC带来的STW

内存分配策略

  • 如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,会被移动到Survivor空间,并且将对象年龄设为1.对象在Survivor区每经过一次Minor GC之后仍然存活的话,年龄就会增加1,当他年龄达到一定程度(HotSpot默认15)时会晋升到老年代
  • 对象晋升到老年代的年龄阈值 设置 -XX:MaxTenuringThreshold
  • 针对不同年龄段对象的分配原则
    • 优先分配到Eden
      • 开发中比较长的字符串或者数组,会直接存放在老年代,但是因为新创建的对象都是朝生夕死的,所以这个大对象可能也很快需要被回收,但因为老年代Major GC触发的次数比Minor GC少,所以回收起来就会比较慢
    • 大对象直接分配到老年代
      • 尽量避免程序中出现过多的大对象
    • 长期存活的对象分配到老年代
    • 动态对象年龄判断
      • 如果Survivor区中相同年龄的所有对象大小之和大于了Survivor空间的一般,此时年龄大于或等于该年龄的对象可以直接进入老年代 无需等到MaxTenuringThreshold
    • 空间分配担保: -XX:HandlePromotionFailure
      • 也就是经过Minor GC后,所有对象都存活,因为Survivor比较小,所有需要将Survivor无法接纳的对象保存到老年代中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值