zoukankan      html  css  js  c++  java
  • (二)垃圾回收

    堆里面存放着Java几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还"活着",哪些已经"死去"


     一、判断对象是否已死

    • 引用计数算法

    描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值+1;当引用失效时,计数器值-1;当计数器值为0时,代表对象不再被使用
    优点:实现简单,效率高
    缺点:当对象之间存在相互循环依赖时,难以解决

    public class ReferenceCountGCTest {
    
    private Object instance;
    
    public static void main(String[] args) throws IOException {
        ReferenceCountGCTest objA = new ReferenceCountGCTest();
        ReferenceCountGCTest objB = new ReferenceCountGCTest();
        objA.instance = objB;
        objB.instance = objA;
    
        objA = null;
        objB = null;
    
        // 触发GC,但不会对objA和objB进行回收,因为objA和objB之间存在相互依赖,计数值不为0
        System.gc();
    }
    • 可达性分析算法

    描述:通过一系列的GC Roots对象作为根节点,然后从这些根节点向下搜索,搜索所经过的路径为"引用链";当一个对象到GC Roots没有任何引用链时,代表对象不再被使用

     如上图所示,object6、object7、object8和object9都无法到达GC Roots根节点,所以会判定为可回收的对象


    二、垃圾回收算法

    • 标记-清除算法

    描述:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象

    缺点:

    1."标记"和"清除"两个过程的效率都不高

    2.标记清除后会产生大量不连续的内存碎片,当分配大对象时,找不到足够的连续空间而不得不提前触发另一次垃圾收集动作

    • 复制算法

    描述:为了解决效率问题,"复制算法"出现了。将内存按容量划分大小相等的两块;每次只使用其中一块内存,当这一块内存用完了,将还存活的对象复制到另一块内存,然后把之前使用过的一块内存空间一次清理掉。内存不连续碎片只要移动堆顶指针,按顺序分配内存即可

    优点:解决了内存碎片问题,实现简单,运行高效

    缺点:内存缩小为原来的一半

    现在的商业虚拟机都采用这种收集算法来回收新生代,IBM研究表明,新生代中的对象98%是"朝生夕死"(活不过1次垃圾回收)的,所以并不需要按照1:1的比例来划分空间,而是将新生代的内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor空间,另外一块Survivor空间进行保留;

    当回收时,将Eden和Survivor空间存活的对象复制到另一块的Survivor空间,然后清理之前使用的Eden和Survivor空间;

    HotSpot虚拟机默认将Eden和两块Survivor空间比例为8:1:1,这样在新生代可用内存空间达到90%(80%+10%),仅10%的内存会被浪费;

    大多情况下,新生代中98%的对象是可回收的,仅剩2%存活对象,另外一块Survivor空间完全够用,但不能保证每次回收都不多于10%的存活对象。当另外一块Survivor空间没有足够内存来存放上一次新生代收集下来的存活对象,则将这些对象通过分配担保机制进入老年代;

    • 标记-整理算法

    复制算法在对象存活率较高时,就要进行频繁的复制操作,效率将会变低。当不想浪费50%的内存空间时,就需要有额外的空间进行分配担保;

    根据老年代的特点(对象存活率高,没有额外空间对它进行分配担保),一般不能直接选用复制算法,而提出了"标记-整理"算法;

    描述:首先标记所有需要回收的对象,然后让所有存活着的对象都向一端移动,最后直接清理掉端边界以外的内存

    • 分代收集算法

    当前商业虚拟机的垃圾收集都采用"分代收集"算法,根据对象存活周期的不同将内存划分为几块,一般把Java堆分为新生代老年代,这样就可用根据各个年代的特点选择最适当的收集算法。
    在新生代中,每次垃圾收集都会有大批对象死去,只有少量存活,所以可用选用复制算法,只需要将少量的存活对象进行复制保留,就可用完成收集;
    在老年代中,因为对象存活率高、没有额外空间对它进行分配担保,就必须使用"标记-清除"或者"标记-整理"算法进行垃圾收集;

  • 相关阅读:
    HDU 5273 Dylans loves sequence 暴力递推
    HDU 5285 wyh2000 and pupil 判二分图+贪心
    HDU 5281 Senior's Gun 贪心
    HDU 5651 xiaoxin juju needs help 逆元
    HDU 5646 DZY Loves Partition
    HDU 5366 The mook jong
    HDU 5391Z ball in Tina Town 数论
    HDU 5418 Victor and World 允许多次经过的TSP
    HDU 5642 King's Order dp
    抽屉原理
  • 原文地址:https://www.cnblogs.com/lwcode6/p/14837534.html
Copyright © 2011-2022 走看看