Java 中的四种引用

Java 中的四种引用

首先,从 JDK1.2 开始,对象的引用被划分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

强引用

强引用(Strong Reference)是使用最普遍的引用。如果一个对象具有强引用,那么它永远不会被 GC。例如:

Object strongReference = new Object();

当内存空间不足时,JVM 宁愿抛出OutOfMemoryError,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

如果强引用对象不使用时,需要弱化从而可以被 GC,例如ArrayList中的clear()方法:
显式地设置强引用对象为null,或让其超出对象的生命周期范围,则垃圾回收器认为该对象不存在引用,就会回收这个对象。具体什么时候收集这要取决于具体的垃圾回收器。

软引用

如果一个对象只具有软引用(Soft Reference),当内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。让我们来看一个例子具体了解一下:

String str = new String("abc");
    SoftReference<String> softReference = new SoftReference<>(str);
    String result = softReference.get();

让我们来看一下get():

public T get() {
        T o = super.get();
        // timestamp代表上一次软引用上一次被使用的时间(初始化、get())
        // clock代表上一次GC的时间
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

因此,软引用在被垃圾回收时,也遵循LRU法则,优先回收最近最少被使用的对象进行回收。

软引用的使用场景多是内存敏感的高速缓存。具体来说,就是我们希望将数据存放到缓存中,这样可以快速进行读取。但是,当 JVM 中内存不够用时,我们又不希望缓存数据会占用到 JVM 的内存。例如配合ReferenceQueue,如果软引用所引用对象被垃圾回收,JVM 就会把这个软引用加入到与之关联的引用队列中:

弱引用

如果一个对象只具有弱引用(Weak Reference),其生命周期相比于软引用更加短暂。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会对它进行回收。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。其使用为:

String str = new String("abc");
    WeakReference<String> weakReference = new WeakReference<>(str);
    str = weakReference.get();

虚引用

虚引用(PhantomReference),顾名思义,就是形同虚设。与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用与软引用和弱引用的一个区别在于:

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要进行垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,也可以理解为一种回调方法。

总结

Java 中4种引用的级别和强度由高到低依次为:强引用 -> 软引用 -> 弱引用 -> 虚引用

强引用:无论内存是否足够,不会回收。

软引用:内存不足时,回收该引用关联的对象。

弱引用:垃圾回收时,无论内存是否足够,都会回收。

虚引用:任何时候都可能被垃圾回收器回收。

# JVM  

评论

公众号:mumuser

企鹅群:932154986

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×