精华内容
下载资源
问答
  • 引用计数算法

    千次阅读 2019-08-22 16:18:03
    相比于前面三种垃圾收集算法,引用计数算法算是实现最简单的了,它只需要一个简单的递归即可实现。现代编程语言比如Lisp,Python,Ruby等的垃圾收集算法采用的就是引用计数算法。现在就让我们来看下引用计数算法...

    前言

    相比于前面三种垃圾收集算法,引用计数算法算是实现最简单的了,它只需要一个简单的递归即可实现。现代编程语言比如Lisp,Python,Ruby等的垃圾收集算法采用的就是引用计数算法。现在就让我们来看下引用计数算法(reference counting)是如何工作的。

    算法原理

    引用计数算法很简单,它实际上是通过在对象头中分配一个空间来保存该对象被引用的次数。如果该对象被其它对象引用,则它的引用计数加一,如果删除对该对象的引用,那么它的引用计数就减一,当该对象的引用计数为0时,那么该对象就会被回收。

    比如说,当我们编写以下代码时,

    String p = new String("abc")
    

    abc这个字符串对象的引用计数值为1.

     

     

    而当我们去除abc字符串对象的引用时,则abc字符串对象的引用计数减1

    p = null
    

    由此可见,当对象的引用计数为0时,垃圾回收就发生了。这跟前面三种垃圾收集算法不同,前面三种垃圾收集都是在为新对象分配内存空间时由于内存空间不足而触发的,而且垃圾收集是针对整个堆中的所有对象进行的。而引用计数垃圾收集机制不一样,它只是在引用计数变化为0时即刻发生,而且只针对某一个对象以及它所依赖的其它对象。所以,我们一般也称呼引用计数垃圾收集为直接的垃圾收集机制,而前面三种都属于间接的垃圾收集机制。

    而采用引用计数的垃圾收集机制跟前面三种垃圾收集机制最大的不同在于,垃圾收集的开销被分摊到整个应用程序的运行当中了,而不是在进行垃圾收集时,要挂起整个应用的运行,直到对堆中所有对象的处理都结束。因此,采用引用计数的垃圾收集不属于严格意义上的"Stop-The-World"的垃圾收集机制。这个也可以从它的伪代码实现中看出:

    New(): //分配内存
        ref <- allocate()
        if ref == null
            error "Out of memory"
        rc(ref) <- 0  //将ref的引用计数(reference counting)设置为0
        return ref
    
    atomic Write(dest, ref) //更新对象的引用
        addReference(ref)
        deleteReference(dest)
        dest <- ref
    
    addReference(ref):
        if ref != null
            rc(ref) <- rc(ref)+1
            
    deleteReference(ref):
        if ref != null
            rc(ref) <- rc(ref) -1
            if rc(ref) == 0 //如果当前ref的引用计数为0,则表明其将要被回收
                for each fld in Pointers(ref)
                    deleteReference(*fld)
                free(ref) //释放ref指向的内存空间
    

    对于上面的伪代码,重点在于理解两点,第一个是当对象的引用发生变化时,比如说将对象重新赋值给新的变量等,对象的引用计数如何变化。假设我们有两个变量p和q,它们分别指向不同的对象,当我们将他们指向同一个对象时,下面的图展示了p和q变量指向的两个对象的引用计数的变化。

    String p = new String("abc")
    String q = new String("def")
    p = q
    

    当我们执行代码p=q时,实际上相当于调用了伪代码中的Write(p,q), 即对p原先指向的对象要进行deleteReference()操作 - 引用计数减一,因为p变量不再指向该对象了,而对q原先指向的对象要进行addReference()操作 - 引用计数加一。

    第二点需要理解的是,当某个对象的引用计数减为0时,collector需要递归遍历它所指向的所有域,将它所有域所指向的对象的引用计数都减一,然后才能回收当前对象。在递归过程中,引用计数为0的对象也都将被回收,比如说下图中的phone和address指向的对象。

    环形数据问题

    但是这种引用计数算法有一个比较大的问题,那就是它不能处理环形数据 - 即如果有两个对象相互引用,那么这两个对象就不能被回收,因为它们的引用计数始终为1。这也就是我们常说的“内存泄漏”问题。比如下图展示的将p变量赋值为null值后所出现的内存泄漏。

    后记

    到今天为止,四种基本的垃圾收集算法就都介绍完了。每种算法都有它自己的优点和缺点。同时每种基本算法还有它自己的优化算法,但是在这里我只专注于介绍基本的原理,让大家知道它们是怎么工作的,对于它们的优化算法,大家可以自己查阅资料进行学习。后面我们会来看下这几种基本垃圾收集算法怎么组合成更加高级的垃圾收集算法,比如说分代垃圾收集算法等。

     

    展开全文
  • 引用计数算法优缺点

    2021-08-11 07:59:29
    引用计数算法的优点 发现垃圾时立即回收:根据当前的引用数是否为 0 来决定这个对象是不是垃圾,如果找到了可以立即释放 最大限度减少程序暂停:应用程序在执行的过程中,必然会对内存进行消耗,而当前的执行平台...

    引用计数算法的优点

    • 发现垃圾时立即回收:根据当前的引用数是否为 0 来决定这个对象是不是垃圾,如果找到了可以立即释放
    • 最大限度减少程序暂停:应用程序在执行的过程中,必然会对内存进行消耗,而当前的执行平台内存肯定是有上限的,内存有占满的时候,不过由于引用计数算法是时刻监控着引用对象,当内存要占满的时候,引用计数立马找到数字为 0 的对象,对其进行释放,所以保证了内存不会有占满的时候。

    引用计数算法的缺点

    • 无法回收循环引用的对象:

    fn函数调用结束后,在全局下找不到 obj1 和 obj2 但是 fn 作用域范围内,obj1 和 obj2 有一个互相的指引关系,在这种情况下,它们身上的引用计数器中的数值并不是为 0 的,引用计数下的GC就没有办法将它们回收了,从而造成了内存空间的浪费

    function fn() {
        const obj1 = {}
        const obj2 = {}
    
        obj1.name = obj2 // 对象循环
        obj2.name = obj1 // 引用数值并不为 0 ,不会释放空间,造成空间浪费
    
        return "deyang is a coder" 
    }
    
    fn()
    • 时间开销大:当前的引用计数需要去维护数值的变化,这种情况下要时刻的监控当前对象的引用数值是否需要修改,本身来说对象数值的修改就要消耗时间,如果有更多的对象需要修改,那么时间就会显得更大一些。所以引用计数算法相对于其它GC算法来说,时间开销会更大一些
    展开全文
  • 一、引用计数算法的概述 引用计数算法的实现很简单,其判断效率也很高,实现的基本思路是:给对象添加一个引用计数器,每当有一个地方引用 它时,计数器的值就会加1;当引用失效以后计数器的值就会减1;任何时刻...

    一、引用计数算法的概述
    引用计数算法的实现很简单,其判断效率也很高,实现的基本思路是:给对象添加一个引用计数器,每当有一个地方引用 它时,计数器的值就会加1;当引用失效以后计数器的值就会减1;任何时刻计数器都为0的对象都是不能再被使用的对象。但是在Java语言中并没有使用引用计数器算法来管理内存,其主要原因是:它很难解决对象之间相互循环引用的问题。
    举个简单的例子,请看代码中的testGC方法 :对象 objA 租objB 都有字段in tance,赋值令objA.instan =objB以及objB.instan =objA。除此之外,这两个对象再无任何引用,实际上这两个对象不可能再被访问,但是它们因为相互引用对方,导致计数器不为0,因此不能通过引用计数算法通知垃圾回收器回收它们。
    在这里插入图片描述
    二、浅谈引用
    在JDK1.2 立后,Java 对引用的概念进行了扩充,将引用分为强引用 Strong Reference ) 、软引用 (Soft Reference) 、弱引用 (Weak Reference) 、虚引用 (Phantom Reference) 四种,这四种引用强度依次远惭减弱。
    强引用:在程序代码中普遍存在的,类似于 Object obj = new Object() 这类的引用,只要强引用存在,垃圾回收器永远不会回收被引用的对象。
    软引用:用来描述一些还有用,但并非必须的对象,对于软引用关联着的对象,在系统将要发生内存溢出、抛出异常之前,会把这些对象列入回收范围之内进行二次回收。如果这次回收后还没有足够的空间,则会出现加内存溢出。
    弱引用:弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联着的对象只能生存到下一次垃圾回收之前。当垃圾回收器工作时,无论内存是否溢出,该对象都会被垃圾回收器回收。
    虚引用:也成为幽灵引用或者幻影引用,它是一种最弱的引用关系。一个对象是否有虚引用的存在,完全不会影响其生存时间,也我无法通过虚引用来获取一个对象的实例。为一个对象设置虚引用关联的唯一目的是希望能在这个对象呗回收时收到一个系统通知。

    展开全文
  • 引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。 引用计数算法(ReferenceCounting)的实现...

    引用计数算法

    给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

    引用计数算法(ReferenceCounting)的实现简单,判定效率也很高,但是在Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。

    比如俩个对象objA和objB都有字段instance,赋值令objA.instance=objB及objB.instance=objA,除此之外,这两个对象再无任何引用,实际上这两个对象已经不可能再被访问,但是它们因为互相引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们。如下伪代码所示:

    objA = new Obj();
    objB = new Obj();
    
    objA.instance=objB;
    objB.instance=objA;

    可达性分析算法

    Java虚拟机通过可达性分析(ReachabilityAnalysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GCRoots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(ReferenceChain),当一个对象到GCRoots没有任何引用链相连时,则证明此对象是不可用的。

    如图所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GCRoots是不可达的,所以它们将会被判定为是可回收的对象。可达性分析算法判定对象是否可回收在Java语言中,可作为GCRoots的对象包括下面几种:
            1、虚拟机栈(栈帧中的本地变量表)中引用的对象。
            2、方法区中类静态属性引用的对象。
            3、方法区中常量引用的对象。
            4、本地方法栈中JNI(即一般说的Native方法)引用的对象。

    展开全文
  • 引用计数算法 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有—个地方引用它时,计数器值就加1 ; 当引用失效时,计数器值就减1 ; 任何时刻计数器为0的对象就是不可能再被使用的。 客观...
  • 引用计数算法解析

    2019-12-20 20:40:09
    引用计数算法导语 导语
  • 在阅读西门吹牛和Gityuan的文章之后,总结记录下引用计数算法的循环引用问题。示例代码如下:public static void main(String[] args) { GcObject obj1 = new GcObject(); //Step1 GcObject obj 2 = new GcObject...
  • 引用计数算法: 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。 ...
  • 很多教科书判断对象是否存活的算法是这样的... 客观的说,引用计数算法(Reference Counting)的实现简单,判定效率也很高,在大部分情况下她都是一个不错的算法,也有一些比较著名的应用案例,例如微软公司的COM(C...
  • 引用计数算法的缺陷

    2019-09-02 22:20:45
    public class ReferenceCountingGC { public Object instance = null; private static final ...592k->0k意味着虚拟机还是回收了相互引用的两个对象,侧面说明虚拟机并不是通过引用计数算法来判断对象是否存活
  • 很多文章以及Java虚拟机相关的书籍,都会告诉你如果采用引用计数算法,上述代码中obj1和obj2指向的对象已经不可能再被访问,彼此互相引用对方导致引用计数都不为0,最终无法被GC回收,而可达性算法能解决这个问题。...
  •  1.GC时候的引用计数  2.GC的时候根搜索算法 一、GC时候的引用计数  对象一旦被使用,计数器会进行+1操作,当对象取消引用计数器-1操作,当为0时被标示为垃圾。此种标示方法的弊端在于已经死亡的对象如果存在...
  • 引用计数算法是常用的内存管理算法,该算法的缺陷是会产生循环引用,导致对象永远不会被回收。下面证明JVM不是通过引用计数算法来判断对象是否存活。 //Debug Configuration: //-verbose:gc: -Xms20M -Xmx20M...
  • Java程序运行时,所有的实例对象都保存在Java堆里,而大量的实例对象会占用大量的内存空间,保证内存的可用性,... 下面介绍两种判断对象是否还会被引用的算法——引用计数算法和可达性分析法 引用计数算法: ...
  • 由此我们看出,a和b在置为null之后,这两个对象已经不可能再被访问了,但是因为它们互相引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们。虚拟机这么牛气,自然不会用这样的方法...
  • 引用计数算法在每个对象都维护着一个内存字段来统计它被多少”部分”使用—引用计数器,每当有一个新的引用指向该对象时,引用计数器就+1 ,每当指向该引用对象失效时该计数器就-1 ,当引用数量为0的时候,则说明对象没有...
  • 判断对象的存活一般有两种方式:引用计数算法 和 可达性分析算法。 一、引用计数算法(Java未使用) 1、原理: 引用计数算法,对每个对象保存一个整型的引用计数器属性。用于记录对象被引用的情况。 对于一个对象A,...
  • 引自知乎 垃圾回收机制中,引用计数法是如何维护所有对象引用的? @Gityuan 的回答 如何区分垃圾。 从一段代码来分析整个过程,并结合模型图来简易讲解,希望能让大家对彻底明白。 先简单说说 Java运行时内存区...
  • 引用计数算法与根搜索算法引用计数算法根搜索算法 引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不可能再被...
  • 引用计数算法则可以通过引用关系的创建和删除直接确定对象的存活状态,而不用像追踪式回收器一样。  在引用计数算法中,每个对象都维护了一个引用计数器,该值通常在对象头中。 伪代码简单的引用计数算法 New()...
  • GC之引用计数算法

    2019-09-25 18:38:24
    我们都知道c++程序在...引用计数算法是为每个对象一个计数器用来保存对象被引用的次数,如果该对象被其他对象引用,计数器加1,对该对象引用结束则计数器减1,当计数器为0时认为该对象已经没有任何引用,就会被回...
  • 引用计数算法2.可达性分析算法 垃圾标记阶段算法包括引用计数算法和可达性分析算法。 在进行垃圾回收之前,需要判断哪些对象是存活对象,哪些是死亡对象,只有被标记为死亡的对象才能够被回收。 当一个对象已经不再...
  • 引用计数算法作为垃圾收集器最早的算法,有其优势,也有其劣势,虽然现在的JVM都不再采用引用计数算法进行垃圾回收【例如Sun的Java hotspot采用了火车算法进行垃圾回收】,但这种算法也并未被淘汰,在著名的单进程高...
  • 判断java对象是否需要存活的两种算法:引用计数算法和可达性分析算法 1.引用计数算法 原理: 每当一个地方应用,计数器值就加一,当引用失效的时候,计数器就减一。 优缺点: 效率很高,但是无法解决对象之间...
  • 介绍了Java中的垃圾分析算法,包括引用计数法和可达性分析算法的原理!
  • 垃圾回收比较核心的几个问题是 1.如何判定对象为垃圾对象? ...本文学习引用计数算法 引用计数算法 在A对象(在堆内存中)中添加一个引用计数器,当内存中有地方引用这个A对象的时候,引用计...
  • Garbage Collection | 引用计数算法

    万次阅读 2016-10-09 21:37:23
    这是一个比较直接的算法,其基本手段是为每一个单元计算指向它的引用(来自其他活动单元或者根)的数量【Collins,1960】.它的优点在于能够非常简单的判断单元是否
  • java通过虚拟机的GC机制来完成不使用对象的回收,虚拟机判断对象是否存活的方法有两种,分别是引用计数算法和可达性分析算法。 引用计数算法 为对象添加一个引用计数器,每当有位置引用它的时候,计数器的值就加1,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 81,657
精华内容 32,662
关键字:

引用计数算法