引用计数法和gcroot的优缺点

借鉴:https://it.sohu.com/a/696915252_121124363
https://blog.csdn.net/baidu_37313657/article/details/103824389
https://blog.csdn.net/weixin_42620326/article/details/115530478
https://blog.csdn.net/qq_44787816/article/details/119239324
https://www.jianshu.com/p/4adbcea91888

一:引用计数法的优缺点

当一个对象被引用时,引用计数器加一;当一个引用被释放时,引用计数器减一。通过不断地增减引用计数器,系统可以动态地追踪对象的引用情况,并在适当的时候回收不再被引用的对象。

1.优点:
实时性好:当没有引用指向一个对象时,该对象可以立即被回收,释放内存资源。
简单高效:引用计数法是一种相对简单的内存管理技术,实现起来较为高效。
没有必要沿指针查找:引用计数法和 GC 标记 - 清除算法不一样,没必要由根沿指针查找。

2.缺点:
循环引用问题:当存在循环引用的情况下,对象之间的引用计数可能永远不会为零,导致内存泄漏的发生。
额外开销:每个对象都需要维护一个引用计数器,这会带来一定的额外开销。
不支持并发:引用计数法在多线程环境下需要进行额外的同步操作,以确保引用计数的准确性,这可能导致一定的性能损失。
实现烦琐复杂:引用计数的算法本身很简单,但事实上实现起来却不容易

二:gcroot的优缺点

1.概念:

GC root原理:通过对枚举GCroot对象做引用可达性分析,即从GC root对象开始,向下搜索,形成的路径称之为
引用链。如果一个对象到GC roots对象没有任何引用,没有形成引用链,那么该对象等待GC回收。

引用计数法和gcroot的优缺点_第1张图片
通俗理解:

假设我们现在有三个实体,分别是 人,狗,毛衣
然后他们之间的关系是:人 牵着 狗,狗穿着毛衣,他们之间是强连接的关系
有一天人消失了,只剩下狗狗 和 毛衣,这个时候,把人想象成 GC Roots,因为 人 和 狗之间失去了绳子连接,
那么狗可能被回收,也就是被警察抓起来,被送到流浪狗寄养所
假设狗和人有强连接的时候,狗狗就不会被当成是流浪狗

Java中可以作为GC Roots的对象:
(1)虚拟机栈(javaStack)(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
(2)方法区中的类静态属性引用的对象。
(3)方法区中常量引用的对象。
(4)本地方法栈中JNI(Native方法)引用的对象。


/**
 * 在Java中,可以作为GC Roots的对象有:
 * - 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中的引用对象
 * - 方法区中的类静态属性引用的对象
 * - 方法区中常量引用的对象
 * - 本地方法栈中的JNI(Native方法)的引用对象,例如线程里start()方法
 *   
 */
public class GCRootDemo {


    // 方法区中的类静态属性引用的对象
    private static GCRootDemo2 t2;

    // 方法区中的常量引用,GC Roots 也会以这个为起点,进行遍历
    private static final GCRootDemo3 t3 = new GCRootDemo3(8);

    public static void m1() {
        // 第一种,虚拟机栈中的引用对象
        GCRootDemo t1 = new GCRootDemo();
        System.gc();
        System.out.println("第一次GC完成");
    }
    public static void main(String[] args) {
        m1();
    }
}

2.优点:
解决了部分循环引用的问题
3.缺点:
可达性分析算法的缺点是在处理循环引用的情况时,可能会存在一些无法回收的对象。如果两个对象互相引用,但是两个对象都没有被GC Roots引用,那么这两个对象就会被视为无用对象。但实际上它们互相引用,应该互相保留。为了解决这个问题,一般需要结合其他算法进行处理,例如引用计数算法。

你可能感兴趣的:(java)