Java的强、软、弱、虚引用

小熊博客
2021-08-24 / 1 评论 / 238 阅读
温馨提示:
本文最后更新于2021-08-24,若内容或图片失效,请留言反馈。

finalize()

finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法。

我们先重写一下finalize方法加一个输出方便查看Jvm何时回收引用

public class M {                                    
    //重写此方法主要用来观察是否进行了回收                            
    @Override                                       
    protected void finalize() throws Throwable {    
        System.out.println("回收");                   
        super.finalize();                           
    }                                               
}                                                   

强引用

某一个变量直接指向new出来的某一块内存区域,我们把它称之为强引用。当内存区域没有被任何变量指向的时候Jvm回直接回收掉这块区域。我们来看案例

public class strongReference {
    public static void main(String[] args) throws IOException {
        //强引用
        M m=new M();
        m=null;
        System.gc();
        System.in.read();//阻塞线程看效果
    }
}

运行以上main方法,输出结果如下,可以看到我们重写的finalize()方法被调用了,证明一旦没有变量指向的强引用内存区域Jvm会直接回收掉。

image.png

软引用

软引用是使用SoftReference创建的引用,被引用的对象在内存不足的时候才会被Jvm回收。

public class softReference {
    public static void main(String[] args) {
        String s=new String("小熊");//强引用
        SoftReference<String> softReference=new SoftReference<>(s);//软引用 指向了new String("小熊");
        s = null;//s指向null
        System.out.println(softReference.get());
    }
}

这里变量s持有对字符串对象的强引用,而softReference持有了该对象的软引用,虽然执行了s = null强引用关联取消,但是还剩softReference软引用new String("小熊")这块内存区域不会被回收,但是在内存不足发生Full GC这个字符串对象会被回收。

弱引用

只要遭遇到GC就会被回收

public class weakReference {
    public static void main(String[] args) {
        WeakReference<M> weakReference=new WeakReference<>(new M());//弱引用指向m
        System.out.println(weakReference.get());
        System.gc();
        System.out.println(weakReference.get());
    }
}

image.png

虚引用

虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。和弱引用很相似,那么它和弱引用的区别又是什么呢?虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。你声明虚引用的时候是要传入一个queue的。当你的虚引用所引用的对象已经执行完finalize函数的时候,就会把对象加到queue里面。你可以通过判断queue里面是不是有对象来判断你的对象是不是要被回收了。