- 对象回收判定
- 引用计数器方法
- 可达性分析方法
- GC Root
- 垃圾回收过程
- 第一次标记
- 对象放入F-Queue等待执行finalize方法
- 执行F-Queue队列中等待执行的finalize方法,将对象放入“即将回收”集合中
- 回收“即将回收”的集合中的所有对象
- 垃圾回收算法
- 标记清除
- 复制算法
- 标记整理
- 安全点(Safe point)
对象回收判定
引用计数器方法
给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用失效时,计数器就减1。优点是判定简单,效率也很高。缺点是无法解决相互循环引用的问题。
可达性分析方法
从GC Roots出发一直沿着引用链向下寻找,如果某个对象不能通过GC Roots寻找到,那么虚拟机就认为该对象可以被回收。
GC Root
- 虚拟机栈(栈桢中的本地变量表)中的引用的对象
- 方法区中的类静态属性引用的对象
- 方法区中的常量引用的对象
-
本地方法栈中JNI(Native方法)的引用的对象
垃圾回收过程
第一次标记
当对象进行可达性分析没有与GC Roots相连的引用链,将会被第一次标记。并根据是否需要执行finalize()方法进行一次筛选,对象没有重写finalize()或者虚拟机已经调用过finalize(),都被视为不需要执行
对象放入F-Queue等待执行finalize方法
如果对象有必要执行finalize,会被放入到F-Queue队列中,并在稍后由虚拟机自动创建的低优先级的Finalizer线程去触发它,并不保证等待此方法执行结束。没有重写或已执行过,则不会有此步骤
执行F-Queue队列中等待执行的finalize方法,将对象放入“即将回收”集合中
Finalizer线程执行F-Queue队列中的finalize方法时,将是对象自救的最后一次机会。如果方法的执行使得对象被其他变量或对象所引用,则GC Roots变为可达,GC将会把它移出“即将回收”的对象集合。如果它没有自救,那它就只能等待回收了。
回收“即将回收”的集合中的所有对象
具体的对象回收过程,根据不同的GC,会有不同的过程。
垃圾回收算法
标记清除
先标记出所有要回收的对象,在标记完成后统一进行对象的回收。有两个不足:
- 是效率问题,标记和清除的效率都不高。
-
是空间问题,会产生大量不连续的内存碎片,碎片太多会都导致大对象无法找到足够的内存,从提前触发垃圾回收。
复制算法
内存分为一个Eden,两个Survival空间,默认比例是8:1。回收时,将Eden和一个Survival的存活对象全部放入到另一个Survival空间中,最后清理掉刚刚的Eden和Survival空间
标记整理
先标记存活对象,将存活对象移动到一端,然后直接清理掉端边界以外的对象
安全点(Safe point)
safepoint指的特定位置主要有:
- 循环的末尾 (防止大循环的时候一直不进入safepoint,而其他线程在等待它进入safepoint)
- 方法返回前
- 调用方法的call之后
- 抛出异常的位置