判断对象可回收

  1. 引用计数法
  2. 可达性分析算法(√)

    可达性分析算法

    以 GC Roots 作为起点,没有与 GC Roots 引用链相连的对象,且没有必要再执行 finalize() 方法时,判断为可回收对象。

    GC Roots

  3. 虚拟机栈中引用的对象

  4. 方法区中静态属性引用的对象
  5. 方法区中常量引用的对象
  6. 本地方法栈中JNI(即Native方法)引用的对象
  7. Java 虚拟机内部的引用(基本数据类型对应的Class对象、常驻的异常对象 NullPointException等、系统类加载器);
  8. 所有被同步锁(synchronized)持有的对象;

    方法区的回收

    虽然大部分垃圾回收都发生在堆内存中,而且方法区垃圾收集的性价比通常也是较低的。但针对方法区,还是有两部分主要回收的内容:废弃常量和不再使用的类型。

常量是否废弃判断:

  1. 没有任何字符串对象引用常量池中的该常量;
  2. 虚拟机中也没有其他地方引用这个字面量;

类型是否不再使用判断:

  1. 该类的实例都已经被回收;
  2. 加载该类的类加载器已经被回收;
  3. 该类对应的 Class 对象没有任何地方引用(没有地方通过反射访问该类);

    垃圾收集算法

  4. 标记-清除法

  5. 标记-复制
  6. 标记-整理

    分代收集分类

  7. 部分收集(Partial GC)

    1. 新生代收集(Minor GC/ Young GC):只收集新生代
    2. 老年代收集(Major GC/ Old GC):只收集老年代(CMS)
    3. 混合收集(Mixed GC):整个新生代和部分老年代(G1)
  8. 整堆收集(Full GC):收集整个 Java 堆和方法区

    分代回收

    根据分代垃圾回收,堆内存被分为新生代、老年代区域,新生代与老年代的空间大小比为 1:2。新生代又分为 Eden 、 From Survivor 和 To Survivor,Eden、From 和 To 的空间大小比为 8:1:1。
    image.png

    对象的流转

  9. 对象优先分配在 Eden;

  10. Eden 区空间不足时,触发 Minor GC,Eden 和 From 依然存活的对象直接复制到 To Survivor,分代年龄增加 1;
  11. 交换 From 与 To;
  12. 新生代对象移动到老年代分为两种情况:
    1. 分代年龄达到 15;
    2. 幸存区相同年龄的对象超过一半,大于等于该年龄的对象移动到老年代;
  13. 大对象直接进入老年代;

    垃圾收集器

    Serial

    单线程、垃圾收集时暂停用户线程

  14. 新生代:标记-复制

  15. 老年代:标记-整理

    ParNew

    多线程并行收集、垃圾收集时暂停用户线程、新生代收集器

  16. 新生代:标记-复制

    Parallel Scavenge

    多线程并行收集、吞吐量优先、新生代收集器

  17. 新生代:标记-复制

    Parallel Old

    多线程并行收集、老年代收集器

  18. 老年代:标记-整理

    CMS

    响应时间优先、最短回收停顿时间

  19. 老年代:标记-清除

收集步骤:

  1. 初始标记(STW)
  2. 并发标记
  3. 重新标记(STW)
  4. 并发清除

    G1 —— Garbage First

收集步骤

  1. 初始标记(STW)
  2. 并发标记
  3. 最终标记(STW)
  4. 筛选回收(STW)