vlambda博客
学习文章列表

GC算法(垃圾标记阶段)

概述

GC算法(垃圾标记阶段)


垃圾标记阶段的算法主要判断对象是否存活。在堆中存放的实例对象,在GC回收之前,通过标记算法标记需要清理的死亡对象和存活对象。只有被标记成死亡对象则进行GC回收对象并释放内存,因此这个阶段被称为 垃圾标记阶段。
  • 该阶段判断存活对象有引用计数算法和可达性分析算法




GC算法(垃圾标记阶段)

引用计数算法

GC算法(垃圾标记阶段)
给每个对象分配一个计数器,每当这个对象被指针指向时,计数器+1。当这个对象的某个指针引用失效时,计数器-1。当计数器为0时(对象废弃,无其他引用),这个对象将被GC进行回收。

优点

  • 较高的实时性:计数器为0就可以触发GC回收,无需等待内存情况再GC。

  • 局部性:每个对象都包含各自的计数器,因此GC只针对具体的对象进行不会涉及到整体


缺点

  • 浪费cpu性能

  • 当每次对象被引用或者引用失效时,计数器都会进行计算。但是对于循环引用引用计数器无法进行解决。一个闭环的循环引用,由于计数器都不为0 ,因此并不会被GC,造成内存溢出也是并不奇怪的。

class one { public three useThree;}
class two { public one useOne;}
class three { public two useTwo;}
public class ObjectSurvival { public static void main(String[] args) { three useThree = new one().useThree; one useOne = new two().useOne; two useTwo = new three().useTwo; }}

GC算法(垃圾标记阶段)

目前在Java中已经被废弃了。




GC算法(垃圾标记阶段)

GCROOTS

GC算法(垃圾标记阶段)
特指垃圾收集器的对象,GC在回收的时候,会回收不是GCROOTS对象或者没有被GCROOTS引用的对象。
public class Common { private String value;}


什么类型的对象可以作为GCROOTS

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象

public class GCROOTS {
public static void main(String[] args) { Common common = new Common(); common = null; }}

    “common“是栈帧中的本地变量,是GCROOTS。当”common“ = null,”common“ 断开了与new Common()的联系,因此会被GC回收。


  • 方法区中类静态属性引用的对象

public class GCROOTS_static { private static Common common;
public static void main(String[] args) { GCROOTS_static gcroots_static = new GCROOTS_static(); gcroots_static.common = new Common(); gcroots_static = null; }}

       “gcroots_static ”是栈帧中的本地变量,是GCROOTS,”common“是对其他实例对象的静态引用。new Common() 给变量”common“赋值了引用且”common“为静态引用,因此是一个GCROOTS。当”gcroots_static” = null断开了与new GCROOTS_static()的联系因此会被回收,而“common”不会被回收。


  • 方法区中常量引用的对象

public class GCROOTS_const { private static final Common common = new Common(); //常量引用对象
public static void main(String[] args) { Common common1 = new Common(); //新实例对象,对照对象 common1 = null; }}

    对于常量引用的对象属于静态不会跟随其他引用的回收而回收。


  • 本地方法栈中JNI中引用的对象

    • 一般说的本地native方法



GC算法(垃圾标记阶段)

可达性分析算法

在可达性算法中是以GCROOTS对象为起点开始搜索。如果一个对象和GCROOTS对象之间没有可达的路径,则称该对象是不可用的。


  • 在使用可达性算法的过程中,内存中的存活对象都会被跟对象集合(GC Root Set)直接或者间接链接着,所走过的路径为引用链。

  • 没有被GCROOTS引用链直接或者间接链接的对象可以被标记为可回收对象。