【JVM】3.1、垃圾收集器(一)

  • 对象回收判定
    • 引用计数器方法
    • 可达性分析方法
      • GC Root
  • 垃圾回收过程
    • 第一次标记
    • 对象放入F-Queue等待执行finalize方法
    • 执行F-Queue队列中等待执行的finalize方法,将对象放入“即将回收”集合中
    • 回收“即将回收”的集合中的所有对象
  • 垃圾回收算法
    • 标记清除
    • 复制算法
    • 标记整理
  • 安全点(Safe point)

对象回收判定

引用计数器方法

给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用失效时,计数器就减1。优点是判定简单,效率也很高。缺点是无法解决相互循环引用的问题。

可达性分析方法

从GC Roots出发一直沿着引用链向下寻找,如果某个对象不能通过GC Roots寻找到,那么虚拟机就认为该对象可以被回收。

GC Root
  1. 虚拟机栈(栈桢中的本地变量表)中的引用的对象
  2. 方法区中的类静态属性引用的对象
  3. 方法区中的常量引用的对象
  4. 本地方法栈中JNI(Native方法)的引用的对象


    GC Root

垃圾回收过程

第一次标记

当对象进行可达性分析没有与GC Roots相连的引用链,将会被第一次标记。并根据是否需要执行finalize()方法进行一次筛选,对象没有重写finalize()或者虚拟机已经调用过finalize(),都被视为不需要执行

对象放入F-Queue等待执行finalize方法

如果对象有必要执行finalize,会被放入到F-Queue队列中,并在稍后由虚拟机自动创建的低优先级的Finalizer线程去触发它,并不保证等待此方法执行结束。没有重写或已执行过,则不会有此步骤

执行F-Queue队列中等待执行的finalize方法,将对象放入“即将回收”集合中

Finalizer线程执行F-Queue队列中的finalize方法时,将是对象自救的最后一次机会。如果方法的执行使得对象被其他变量或对象所引用,则GC Roots变为可达,GC将会把它移出“即将回收”的对象集合。如果它没有自救,那它就只能等待回收了。

回收“即将回收”的集合中的所有对象

具体的对象回收过程,根据不同的GC,会有不同的过程。


垃圾回收算法

标记清除

先标记出所有要回收的对象,在标记完成后统一进行对象的回收。有两个不足:

  1. 是效率问题,标记和清除的效率都不高。
  2. 是空间问题,会产生大量不连续的内存碎片,碎片太多会都导致大对象无法找到足够的内存,从提前触发垃圾回收。


    标记清除法

复制算法

内存分为一个Eden,两个Survival空间,默认比例是8:1。回收时,将Eden和一个Survival的存活对象全部放入到另一个Survival空间中,最后清理掉刚刚的Eden和Survival空间


复制算法

标记整理

先标记存活对象,将存活对象移动到一端,然后直接清理掉端边界以外的对象


标记整理法

安全点(Safe point)

safepoint指的特定位置主要有:

  1. 循环的末尾 (防止大循环的时候一直不进入safepoint,而其他线程在等待它进入safepoint)
  2. 方法返回前
  3. 调用方法的call之后
  4. 抛出异常的位置

你可能感兴趣的:(【JVM】3.1、垃圾收集器(一))