java四种引用

1、强引用

只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OOM错误也不会回收这种对象

String str = "hello world"

Object obj = new Object

这种都是强引用,这种引用保存在栈中,堆存放的是引用内容。

当方法运行完后退出方法栈,这种引用不存在,对象才会回收。对于全局变量来说,obj=null,才会触发GC回收。

显式地设置obj为null,或超出对象的生命周期范围,则gc认为该对象不存在引用才会回收。

2、软引用

在内存足够的情况下直接通过使用软引用取值,无需重新加载数据;一个对象只有软引用可达时,内存不足是可以被回收的。基于这种设置,一般可用作缓存。

Browser prev = new Browser();               // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用        
if(sr.get()!=null){ 
    rev = (Browser) sr.get();           // 还没有被回收器回收,直接获取
}else{
    prev = new Browser();               // 由于内存吃紧,所以对软引用的对象回收了
    sr = new SoftReference(prev);       // 重新构建
}

GC如何判断是否可以回收了呢?

google大神解疑:http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html

3、弱引用

与软引用区别在于拥有更短的生命周期,一个对象只有弱引用可达时,无论内存是否充足,GC时都会回收它的内存。

ThreadLocal中ThreadLocalMap.Entry就是弱引用。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中

public class Test {

    private static ReferenceQueue<Ref> queue = new ReferenceQueue<>();


    public static void main(String[] args) throws InterruptedException {
        LinkedList<WeakReference<Ref>> weakList = new LinkedList<WeakReference<Ref>>();
        for (int i = 0; i < 3; i++) {
            WeakRef weakRef = new WeakRef(new Ref("Weak " + i), queue);
            weakList.add(weakRef);
            System.out.println(weakRef.get());
        }


        System.gc();

        Thread.currentThread().sleep(6000);

        Reference<? extends Ref> queueRef = null;
        while ((queueRef = queue.poll()) != null) {
            System.out.println("queue: " + ((WeakRef) queueRef).weakId);
        }
    }
}

class Ref {
    String id;

    // 占用空间,让线程进行回收
    byte[] b = new byte[2 * 1024];


    public Ref(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "ref:" + id;
    }
}

class WeakRef extends WeakReference<Ref> {
    String weakId;

    public WeakRef(Ref ref, ReferenceQueue<? super Ref> q) {
        super(ref, q);
        this.weakId = ref.id;

    }
}
ref:Weak 0
ref:Weak 1
ref:Weak 2
queue: Weak 2
queue: Weak 0
queue: Weak 1

4、虚引用

如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

 public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<String> queue = new ReferenceQueue<String>();
        PhantomReference<String> pr = new PhantomReference<String>(new String("hello world"), queue);
        System.out.println("before gc: " + pr.isEnqueued());
        System.gc();
        Thread.sleep(1000);
        System.out.println("after gc: " + pr.isEnqueued());

    }

//
before gc: false
after gc: true

虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

pr.get()直接返回null,


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值