美文网首页
强引用,软引用,弱引用,虚引用

强引用,软引用,弱引用,虚引用

作者: CodeDuan | 来源:发表于2022-02-17 11:42 被阅读0次

一、强引用

通过new出来的对象就是强引用,比如Object obj = new Object,强引用不会被垃圾回收器回收,当内存空间不足时,Java虚拟机会抛出OutOfMemoryError异常使程序终止。来看一个例子;

声明一个类,使其占大概1Gb的空间,假设我们内存只有2G

public class Obj {
    byte[] objs = new byte[1024*1024*1024];
}

Main方法中创建一个Obj对象:

Obj obj = new Obj();

此时没有任何异常,那么我们来new两个Obj

Obj obj = new Obj();
Obj obj = new Obj();
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

可以看到,当我们new两个Obj时,直接抛出了异常,可见强引用类型不会被垃圾回收器回收。

二、软引用

如果一个对象是软引用,且内存空间足够时,垃圾回收器就不会回收它,如果内存空间不足时,就会回收这些对象的内存。

//软引用
SoftReference<Obj> obj = new SoftReference<Obj>(new Obj());
//强引用
Obj obj2 = new Obj();

如上代码创建了一个软引用和一个强引用,当创建强引用时,内存空间肯定已经不够了,所以上面的弱引用会被回收,我们打印一下看看:

System.out.println(obj.get());
System.out.println(obj2);

输出:
null
.Obj@15db9742

可以看到这个时候弱引用的obj为null,说明他已经被垃圾回收器回收掉了,所以当内存空间不足时,弱引用会被回收。

接下来看一下内存空间足够的情况;

SoftReference<Obj> obj = new SoftReference<Obj>(new Obj());
System.out.println(obj.get());

System.gc();
Thread.sleep(2000);
System.out.println(obj.get());

上面我们只创建了一个弱引用,然后手动调用gc回收,休眠2s保证gc执行完成,这时再打印obj:

.Obj@15db9742
.Obj@15db9742

可以看到手动调用gc回收后,弱引用obj依旧存在,说明当内存空间足够时,弱引用不会被回收。

三、弱引用

弱引用一旦手动调用gc,或者垃圾回收器发现了弱引用对象,无论内存空间是否足够,弱引用都会被回收。

WeakReference<Obj> obj = new WeakReference<Obj>(new Obj());
System.out.println(obj.get());
System.gc();
Thread.sleep(2000);
System.out.println(obj.get());

上面代码创建了一个弱引用,并打印,随后手动调用了gc,再次打印,我们看下结果

.Obj@15db9742
null

可以看到,一旦我们调用gc之后,弱引用就被回收了。

四、虚引用

故名思意:虚,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。看下面一段代码;

ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference<Obj> obj = new PhantomReference<>(new Obj(),referenceQueue);
System.out.println(obj.get());
输出:null

为什么只创建了一个虚引用,却拿不到它呢?因为在虚引用中,无法拿到虚引用的对象。

那么上面的referenceQueue是什么呢?
虚引用创建时,必须指定一个ReferenceQueue对象,可以理解为引用队列,当虚引用被回收时,该对象就会被垃圾回收器放到这个队列中。

ReferenceQueue referenceQueue = new ReferenceQueue();
PhantomReference<Obj> obj = new PhantomReference<>(new Obj(),referenceQueue);
System.gc();
Thread.sleep(2000);
System.out.println(referenceQueue.poll()); 输出:java.lang.ref.PhantomReference@15db9742

所以我们可以通过referenceQueue来判断虚引用对象是否已经被回收。

五、总结

强引用:不会被回收。
软引用:内存不足时会被回收。
弱引用:垃圾回收时会被回收。
虚引用:垃圾回收时会被回收。

相关文章

网友评论

      本文标题:强引用,软引用,弱引用,虚引用

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