对垃圾回收相关算法的理解

垃圾标记阶段算法

判断对象在内存中是否存活。

两种方式来进行判断对象存活

引用计数算法

为每一个对象保存了一个引用计数器算法,具体过程是当A对象被引用时,计数器加一,当引用失效时,计数减一,当计数器为0时,表示该对象不会被使用,可以进行回收。

缺点:该算法无法解决循环引用问题。需要单独的计数属性,增加了内存空间消耗。

可达性分析算法

以根对象集合为起始点,按照从上往下的方式寻找被根对象集合(GC Roots)所直接或者间接连接的对象是否可达,这条链路就被称为引用链,如果不存在这条引用链中的对象,则是可以被回收的对象。

GC Roots可以是哪些对象?

虚拟机栈、本地方法栈、方法区、字符串常量池等地方对堆空间进行引用的,都可以作为 GC Roots 进行可达性分析。

对象的finalization机制

finalize()方法,对象销毁前的回调函数,只会被调用一次。通常在这个方法内执行一些资源释放和清理等功能。

finalization机制提供了允许对象被销毁之前的自定处理逻辑。

注:不要主动调用对象的finalize()方法.可能会造成对象的二次存活;并且该方法执行的时间不固定,可能出现不会执行的情况;可能会影响垃圾回收的性能。

由于finalize()方法的存在,对象一般处于三种状态:

可触及的:从根节点可是遍历,可到达的对象

可复活的:对象可能在finalize()方法调用后复活

不可触及的:被finalize()方法调用,并没有复活,进入不可触及状态。

垃圾回收阶段算法

标记清楚算法

当堆中的有效空间被耗尽,就会停止整个程序,进行标记和清除。

标记指的是:从根节点开始遍历,标记所有被引用的对象(可达对象,正常使用的对象),并非即将被清除的对象。

清除指的是:从头到尾的进行线性遍历,如果发现某个对象没有被标记为可达对象,则将其回收。清除不是置空,而是将清除的对象保存在空闲的地址列表,新对象加载时,会先判断空间是否够,覆盖原有的地址。

优点:基础的算法,容易理解

缺点:效率不高,并且进行回收时,需要停止整个应用程序。清理出来的内存不连续,碎片化。

复制算法

将可用内存按照容量分为大小相等的两个部分,每次只使用一份空间。在垃圾回收的时候,将正在使用的对象复制到另一个部分,然后清除当前内存中的所有对象。

优点:实现简单高效 ,并且保证空间的连续性,不会出现碎片问题

缺点:需要两倍的空间,复制对象,需要维护对象间的引用关系,内存占用和时间开销稍大。

高效性的基础是存活的对象少,垃圾对象多的前提下。

标记压缩算法

第一阶段和标记清除算法一样,从根节点开始标记所有被引用对象。

第二阶段将所有存活的对象按照顺序压缩在内存中的一段,然后对其他位置进行清除。

标记压缩与标记清除的比较

标记压缩比标记清除多了一个整理移动对象的操作。所以本质上标记清除是一个非移动式的回收算法,而标记压缩是移动式的。

优点:内存区域不分散,在给新对象分配内存时,jvm只需要持有一个起始地址。

缺点:移动对象,需要维护对象的引用地址,效率比复制算法低;移动过程中,需要暂停用户程序的运行。

分代收集算法

不同对象的生命周期是不同的,所以根据不同的对象还采取不同的收集方法,以便提高收集效率。一般分为新生代和老年代。

新生代:区域相对较小,对象生命周期短,存活率低,回收频繁。一般采用复制算法,速度快,并且因为有两个伊甸园区,得以让复制算法的内存利用率问题得到环境。

老年代:存放的对象生命周期长,回收不频繁,一般是标记清除和标记清除整理混合实现。

增量收集算法

因为上述算法在垃圾回收过程中会使应用程序处于暂停状态。

增量收集算法将回收线程和应用线程交替进行,收集一小片内存,切换到应用线程,以此反复。算法的基础依旧是标记清楚和复制算法。

分区算法

将一块大的内存分隔成多个小块,每次合理的回收若干个小区间。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值