美文网首页
垃圾收集算法

垃圾收集算法

作者: T_log | 来源:发表于2018-07-18 16:42 被阅读9次

    垃圾收集算法

    1. 在Java内存中,不停的有对象的创建与消亡,在内存一定的情况下,内存的动态分配和垃圾收集都由JVM去帮我们程序员自动完成,那么,JVM在内存回收时的疑问如下

    哪些内存需要被回收
    什么时候回收
    如何回收

    1. 对象已经死了吗?

    java对象几乎全部存放在堆中,垃圾收集的主要区域也是Java堆内存。在垃圾收集器进行垃圾收集时,首先要确定哪些对象还存活,不需要回收,哪些对象已经死去,需要被回收。

    1. 引用计数算法

    给每个对象一个引用计数器,每当有一个地方引用它时,计数器的值就加一,当引用失效时,计数器的值就减1,任何时刻计数器的值为0的对象,代表不可能在被利用。
    引用计数器的优缺点

    1. 实现简单,判断效率高
    2. 难以解决对象之间相互引用的问题
    package com.schoki.jvm.chapter2;
    /**
     * @author : jzb219@gmial.com
     * @description : 测试 objA objB是否会被回收
     * @date : 2018/7/18 下午3:42
     */
    public class ReferenceCountingGC {
    
        public Object instance = null;
    
        private static final int _1M = 1024 * 1024;
    
        /**
         * 该变量的意义在于占点内存,以便在垃圾收集时,可以看到GC日志中,是否会回收
         */
        private byte[] bigSize = new byte[2 * _1M];
    
        public static void main(String[] args) {
            ReferenceCountingGC objA = new ReferenceCountingGC();
            ReferenceCountingGC objB = new ReferenceCountingGC();
            objA.instance = objB;
            objB.instance = objA;
    
            objA = null;
            objB = null;
    
    
            //假设发生GC, objA objB是否会被回收
            System.gc();
        }
    }
    

    运行结果(JDK1.8)

    [GC (System.gc()) [PSYoungGen: 6779K->576K(38400K)] 6779K->584K(125952K), 0.0016589 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    [Full GC (System.gc()) [PSYoungGen: 576K->0K(38400K)] [ParOldGen: 8K->509K(87552K)] 584K->509K(125952K), [Metaspace: 3286K->3286K(1056768K)], 0.0075244 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
    Heap
     PSYoungGen      total 38400K, used 333K [0x0000000795580000, 0x0000000798000000, 0x00000007c0000000)
      eden space 33280K, 1% used [0x0000000795580000,0x00000007955d34a8,0x0000000797600000)
      from space 5120K, 0% used [0x0000000797600000,0x0000000797600000,0x0000000797b00000)
      to   space 5120K, 0% used [0x0000000797b00000,0x0000000797b00000,0x0000000798000000)
     ParOldGen       total 87552K, used 509K [0x0000000740000000, 0x0000000745580000, 0x0000000795580000)
      object space 87552K, 0% used [0x0000000740000000,0x000000074007f690,0x0000000745580000)
     Metaspace       used 3292K, capacity 4496K, committed 4864K, reserved 1056768K
      class space    used 363K, capacity 388K, committed 512K, reserved 1048576K
    

    从运行结果可以看到

    1. 第一行中PSYoungGen ,说明收集器采用的是Parallel Scavenge收集器
    2. 6779K->576K(38400K),回收前是6779K,回收后576K,说明虽然objA和objB存在相互引用,但是依然会被垃圾收集器回收掉,从侧面也说明垃圾收集算法采用的不是引用计数算法
    1. 可达性分析算法

    通过一些列(注意是很多哦,我特么刚开始以为一个应用里面就一个GC Roots)的成为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时(或者说GC Roots到这个对象不可达),则说明这个对象是不可用的
    哪些对象可以作为GC Roots

    1. 虚拟机栈(栈帧中的本地变量表)中引用的对象--代表应用上下文
    2. 方法区中类静态属性引用的对象
    3. 方法区中,常量引用的对象
    4. 本地方法栈中JNI(一般说native方法)引用的对象(注:这个没太搞明白)

    参考
    周志明《深入理解Java虚拟机》

    写在最后

    做一个灵魂和肉体分离的人,灵魂不受肉体的束缚,灵魂可以指挥肉体

    相关文章

      网友评论

          本文标题:垃圾收集算法

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