强-软-弱-虚引用

        如果reference类型的数据中存放的数值是另外一块内存的起始地址,就称这块内存代表着一个引用。为了更好的控制对象的生命周期,提高内存利用率,JDK1.2 之后,java扩充了引用的概念,将引用分为 强引用/软引用/弱引用/和虚引用四种。
  • 强引用(Strong Reference) 只要对象可达就不会被回收,哪怕抛出OOM
  • 软引用(Soft Reference):内存不足的时候才回收
  • 弱引用(Weak Reference):下次gc的时候就回收;
  • 虚引用(Phantom Reference):跟踪对象什么时候被回收

1、强引用 Reference

  • 类似于"Object obj = new Object()"这类的引用,只要垃圾强引用存在,垃圾回收器就不会回收掉被引用的对象;
示例:
//强引用
public class   {
    static Object obj = new Object();
    public static void main(String[] args) {
        Object obj2 = new Object();//一样不会被回收
        Object obj1 = obj;
        obj = null;  //注意引用只是一个地址变量,obj=null, 但是 obj1 = new Object()还存在引用
        System.gc();
        System.out.println("gc 后:obj1-" + obj1);
        System.out.println("gc 后:obj-" + obj);
    }
}
回收的情况:
  • 1、作用域结束;
  • 2、不可达,复制为null;

2、软引用  SoftReference

  • 当内存不够时回收
示例:
public class SoftReferenceTest {
    public static void main(String[] args) {
        Object obj = new Object();
        //在程序发生oom前才会被回收;内存不足的时候才会被回收
        //并且优先回收长时间空闲的对象
        //适合非必须大对象的缓存;
        SoftReference softReference = new SoftReference(obj);
        System.out.println(softReference.get());
    }
}

3、弱引用 WeakReference

  • 强度比软引用更弱,被弱引用关联的对象只能存活到下一次垃圾回收gc之前,当发生gc,无论当前的内存是否充足,都会gc回收掉弱引用关联的对象;
使用示例:

@Data
public class Orange {
    private String name;

    public Orange(String name) {
        this.name = name;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalized~ ");
        super.finalize();
    }
}
public class WeakOrange extends WeakReference<Orange> {

    public WeakOrange(Orange referent) {
        super(referent);
    }
}

public class WeakReferenceTest {

    public static void main(String[] args) {
        Orange orange = new Orange("king");             //强引用
        String str = "king-zz";
        WeakOrange weakOrange = new WeakOrange(orange); //弱引用
        orange = null;
        WeakOrange weakOrange = new WeakOrange(str);    //弱引用-str 此时str不会被回收,因为str在常量池中,gc不会清理常量池
        str = null;
        System.out.println("gc前 " + weakOrange.get());
        System.gc(); // 发生gc
        try {
            sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("gc 后:" +  weakOrange.get());

    }
}

运行结果result:

gc前 Orange(name=king)
finalized~
gc 后:null

4、 虚引用 PhantomReference

  • 引用基本不影响什么,做个标记,在垃圾回收前,处理一些事情。
实例: 跟踪对象什么时候会回收,只有在gc的时候,才会在虚引用队列里取到该值,判断回收前需要做什么。
public class PhantomRef {

    public static void main(String[] args) throws InterruptedException {

        Object obj = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        //todo 必须是对象和队列一起使用才OK;
        PhantomReference phantomReference = new PhantomReference(obj, queue);
        //todo 这里获取的值永远为空,只有在gc的时候,才会在队列的取到这个对象的值,做一些资源的关闭清理;
        System.out.println("phantomReference1 " + phantomReference.get());  //null
        obj = null;
        System.gc(); //gc前会将该对象放入到队列中,然后处理完后再回收
        System.out.println("phantomReference2 " + phantomReference.get());
        sleep(1000);
        System.out.println("queue.poll " + queue.poll());
    }
}

5、小结

    引用让我们更好的控制对象的生命周期,更高效的利用内存,防止内存泄漏。
 
 
 
水滴石穿,积少成多。学习笔记,内容简单,用于复习,梳理巩固。
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值