Java的强引用、软引用、弱引用和虚引用

137 阅读1分钟

强引用

强引用时使用最普遍的引用,如果一个对象具有强引用,垃圾回收器绝对不会回收该对象。

Obeject object = new Object();

当内存不足时,Java虚拟机宁愿抛出OutOfMemoryError错误使程序异常终止,也不会回收强引用的对象来解决内存不足的问题。当强引用不再使用时,例如显示设置object为null断开引用,或者让超出对象的生命周期范围,则GC认为该对象不存在引用,这时就可以回收该对象。

// 设置object为null
object = nul

// 超出对象的生命周期范围
// 对象存储在堆中,引用存储在栈中,方法结束对象不再引用,即可回收
public void test(){
    Obeject object = new Object();
}

ArrayList的clear()方法,可用于删除列表中的元素,该方法的实现就是将维护的数组elementData中每个元素赋值为null。

public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

强引用回收实例:

public class ReferenceTest {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("对象被回收~");
    }
    public static void main(String[] args) {
        ReferenceTest reference = new ReferenceTest();
        reference = null;
        System.gc();
    }
}

结果为

对象被回收~

软引用

如果一个对象只具有软引用,则内存空间充足时,垃圾回收器不会回收它;如果内存空间不足了,就会回收这些对象的内存空间。

软引用可以用来实现内存比较敏感的高速缓存,当空间内存足够时,可以正常拿到缓存,当内存不足时,可以回收这些缓存的空间,不至于马上抛出OutOfMemoryError

软引用就是把对象用SoftReference包裹一下,当需要从软引用获得被包裹的对象时,只需要使用get方法就可以获取到对象。

SoftReference<ReferenceTest> softReference = new SoftReference<>(new ReferenceTest());
System.out.println(softReference.get());

// 该操作会让软引用转为强引用
ReferenceTest reference= softReference.get()

弱引用

弱引用与软引用的区别在于,弱引用的对象拥有更短暂的生命周期。垃圾回收器一旦发现只具有弱引用的对象,不管当前内存空间是否充足,都会回收他的内存。不过,由于垃圾回收器是一个优先级很低的线程,不一定很快发现具有弱引用的对象。

使用弱引用和软引用类似,关键字变成了WeakReference

WeakReference<ReferenceTest> weakReference = new WeakReference<>(new ReferenceTest());
System.out.println(weakReference.get());

虚引用

虚引用并不会决定对象的生命周期,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,再任何时候都可能被垃圾回收器回收。

虚引用必须和引用对应ReferenceQueue联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象内存之前,把这个虚引用加入到与之关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue();
PhantomReference<ReferenceTest> phantomReference = new PhantomReference<>(new ReferenceTest(), queue);
System.out.println(phantomReference.get());