美文网首页
2、java垃圾回收算法

2、java垃圾回收算法

作者: 谷哥得小弟 | 来源:发表于2018-10-10 18:17 被阅读52次

    GC收集机制一般会有几点需要注意:
    1、那些内存需要回收?
    2、什么时候回收?
    3、如何回收?

    本文不会全部讲解完整,只会介绍基础知识,包含如何判断那些内存需要回收、GC回收中常用的收集算法。

    那些内存需要回收?一般有两种算法:可达性分析算法引用计数法
    可达性分析算法:在java和C#中都是采用这种算法来实现判断对象是否存活的。它的基本思想是通过一系列称为 “ GC roots ” 的对象点作为起始节点向下搜索,搜索走过的路劲称为引用链,当一个对象到 GC roots 没有任何引用链相连,称其为不可用的,可以被回收。(下面图片我去其他地方找的)

    可达性分析算法示意图

    引用计数法:它的基本思想是给对象添加一个引用计数器,当有地方引用到它时就加一;当引用失效时,计数器就减一,当计数器等于0 时说明没有可引用的对象,这种方法实现简单,效率也很高,在微软COM技术,Phython语言,游戏脚本等进行了应用。但对于java对象而言这种方式很难处理对象之间的相互引用问题,如A对象和B对象有相互引用,而没有其他的任何引用,本来这种对象应该被回收 的,但由于采用引用计数法计数器不等于0,所以没法回收对象。

    知道那些内存需要回收,那如何进行回收?那就要用到垃圾回收算法了,回收过程比较复杂,先聊一下回收用到的一些算法的思想:

    标记 - 清除算法
    最基础的算法,后面的算法都是基于这个算法进行优化。分为两个过程进行,首先依次对需要回收的对象进行标记;标记完成后再统一清除需要回收的对象。这种方式有两个问题,一个是效率问题:标记和清除都需要耗费大量的时间,效率不高;另一个是空间问题:清除后会留下大量不连续的内存空间,碎片太多会导致需要分配大内存空间时内存不够用,导致新一轮的GC操作。

    标记 - 清除算法示意图

    复制算法:为了提高效率,提出了这个算法,思想是把内存分为大小相同的两块,进行内存回收时,把存活对象复制到另一块内存上去,然后统一清除第一块内存就可以了。这种算法实现简单,不用考虑内存分配时内存碎片问题,直接一半内存进行分配。代价就是内存变小了一半。
    在商业虚拟机中都是采用这种方法来回收新生代,但内存分配比变成了8:1:1,而不是理论的1:1.因为新生代中对象都死的多,存活少。一般用占比为1 的第一块空闲空间,当超过时放入第二快空间,当两块空间都用完时,会将存活的对象通过分配担保机制放入老年代,但这种情况一般不会发生。

    复制算法 示意图

    标记 - 整理 算法:如果在内存中有大量的存活对象就不适合用复制算法了,成本高还很复杂。比如老年代,对此我们采用 标记 - 整理 算法来进行内存回收,它任然是先标记对象,然后对存活对象向一端进行移动,最后清理掉边界以外的内存。

    标记 - 整理 算法 示意图

    分代收集算法:这并不是一个新的收集算法,而是根据内存对象活动周期的长短不同分为新生代和老年代,新生代的对象很容易死亡,存活率低,所以一般采用复制算法进行收集;而老年代的对象存活率高,一般采用 标记 - 清除算法 或者标记 - 整理 算法进行收集。

    相关文章

      网友评论

          本文标题:2、java垃圾回收算法

          本文链接:https://www.haomeiwen.com/subject/estpaftx.html