JVM之GC

101 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

前面我们提到过垃圾回收算法和常见的垃圾回收器,今天我们讲解我们经常所说的GC。

  • MinorGC (Young GC)

    • 当年轻代空间不足时,就会触发MinorGC,这里的年轻代满指的是Eden区满,Survivor满不会引发GC。(每次Minor GC会清理年轻代的内存。)因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。

    • Minor GC会引发STW,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行。

    • Minor GC后Eden区是空的,会把Eden中的所有活的对象都移到Survivor区域中,如果Survivor区中放不下,那么剩下的活的对象就被移到Old generation 中。

    • 关于S1和S2

      • 1.S0和S1是两个大小相等的区域。分配内存空间只会在其中某一个进行,另外一个空间用来辅助新生代进行垃圾回收的,因为新生代的垃圾回收策略基于复制算法,其思想是将Eden区及两个Survivor中的某个区,如S0区里面需要存活的对象复制到另一个空的Survivor区,如S1区,然后就可以回收Eden和S0区里面的死亡对象。下一次回收就对调S0和S1两个区的角色,S1用来存放活对象,而S0用来辅助回收垃圾,如此循环利用。
      • 2.有些文章并不将永久代纳入java堆内存,其实永久代就是我们所说的方法区,而方法区经常被称为Non-Heap(非堆)。仅仅在HotStop虚拟机的实现中才将GC分代收集扩展至方法区,或者说使用永久代来实现方法区,对于其他的虚拟机是不存在永久代这个概念的。
      • 3.并非所有的对象创建都会在Eden区中分配内存空间。对于Serial和ParNew垃圾收集器,通过指定-XX:PretenureSizeThreshold={size}来设置超过这个阈值大小的对象直接进入老年代。
  • Major GC(Old GC)

    • 指发生在老年代的GC,对象从老年代消失时,只有CMS回收器有单收集Old区行为
      • 什么时候GC:
  • Full GC

    • 整堆收集,收集整个Java堆和方法区的垃圾收集触发

    • Full GC执行的情况有如下五种:

      • 调用System.gc()时,系统建议执行Full GC,但是不必然执行

      • 老年代空间不足

      • 方法区空间不足 (永久代或者元空间)

      • 通过Minor GC后进入老年代的平均大小大于老年代的可用内存

      • 由Eden区、survivor spacee(From Space)区向survivor spacel(To Space)区复制时,survivor 区空间不足,对则把该对象转存到老年代,如果老年代的可用内存小于该对象大小,就会触发Full GC

    • Full GC 是开发或调优中尽量要避免的。这样暂时时间会短一些,Major GC 和 Full GC出现STW的时间,是Minor GC的10倍以上

  • Mixed GC

    • G1垃圾回收器所独有的GC方式。
    • G1在什么时候会触发Mixed GC 参数: -XX:InterfaceTestControllernitiatingHeapOccupancyPercent ,他的默认值是45% 。 意思就是说如果老年代占用超过了45% , 就会触发一个叫做混合回收的操作 , 混合回收意味着新生代和老年代一起回收,这时候毫无疑问整个系统线程都会停止。
    • 选定所有Eden Region和全局并发标记计算得到的收益较高的部分Old Region放入CSet,使用多线程复制算法将CSet的存活对象复制到Survivor Region或者晋升到Old Region。