转载

别再找了,一文彻底解析Java 中的弱引用(参考官网)

package java.lang.ref
  public class WeakReference<T> extends Reference<T> {
 }
复制代码

作用:

jdk 官网解释:

弱引用主要实现不阻止它的key或者value 被回收的mapping。直接贴英文吧,翻译水平有限(weak references are for implementing canonicalizing mappings that do not prevent their keys (or values) from being reclaimed)

个人理解:

它的作用是引用一个对象,但是并不阻止该对象被回收。如果使用一个强引用的话,只要该引用存在,那么被引用的对象是不能被回收的。弱引用则没有这个问题。在垃圾回收器运行的时候,如果一个对象的所有引用都是弱引用的话,该对象会被回收

举例:

在举例弱引用之前我先解释下强引用,对比来方便大家理解:

强引用很好理解就是我们平时new 一个对象。例如:

String str = new String("我是强引用");
复制代码

垃圾回收器有一个可达性判断,如果使用一个强引用的话,只要该引用存在,那么被引用的对象是不能被回收的; 单单看文字有点难理解,下面举个例子

public class StrongRefenceDemo {


    static Map<String, String> map;

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

        StrongRefenceDemo demo = new StrongRefenceDemo();
        demo.strongTest();
        System.out.println("gc 发生前:" + map.get("str"));
        System.out.println("开始通知GC");
        //注意,这里只是通过垃圾回收器进行垃圾回收,并不一定马上执行
        System.gc();
        Thread.sleep(1000 * 5);
        System.out.println("gc 发生后:" + map.get("str"));

    }


    /**
     * 强引用测试
     */
    public void strongTest() {
        String str = new String("我被强引用引用,但是我还没有被垃圾回收");
        map = new HashMap();
        map.put("str", str);
    }

}
复制代码

运行后输出结果:

gc 发生前:我被强引用引用,但是我还没有被垃圾回收
开始通知GC
gc 发生后:我被强引用引用,但是我还没有被垃圾回收

复制代码

相信大家对上面的结果没什么疑问,毕竟str 还是被一个强引用map 引用,垃圾回收器是不能回收它的。

但是这里我有一个好奇,假如这里的str 指向的对象在执行完strongTest()方法 以后用不着了,但是我可能又不是很好的判断去主动调用remove 来移除它。想要垃圾回收器自己判断回收掉可不可以呢?答案其实是可以的,这个时候就是弱引用上场了,请看下面程序

public class WeakRefenceDemo {
    static WeakReference<String> weakReference;
    public static void main(String[] args) throws Exception {

        WeakRefenceDemo demo = new WeakRefenceDemo();
        demo.weakTest();
        System.out.println("gc 发生前:" + weakReference.get());
        System.out.println("开始通知GC");
        //注意,这里只是通过垃圾回收器进行垃圾回收,并不一定马上执行
        System.gc();
        Thread.sleep(1000 * 5);
        System.out.println("gc 发生后:" + weakReference.get());

    }

    /**
     * 弱引用测试
     */
    public void weakTest() {
        String str = new String("我被弱引用引用,但是我还没有被垃圾回收");
        weakReference = new WeakReference(str);
    }


}

复制代码

运行上面代码输出结果

gc 发生前:我被弱引用引用,但是我还没有被垃圾回收
开始通知GC
gc 发生后:null
复制代码

运行结果解析:

这里大家看到输出的是null 也就是意味着已经被垃圾回收器回收掉了。也证明可我们上面说的弱引用并不阻止该对象被回收

使用场景

正常情况下,一个对象应该与它里面包含的对象的生命周期是一致的。打个比方,我有一个全局的map ,那么这个map和它里面的对象的生命周期应该是一致的。假如说一个map 里面的对象的生命周期是比map 对象本身的生命周期要长,在我们没有主动调用map 的remove 方法的时候,垃圾回收器是不会回收掉该对象的。如果这种生命周期相对短的对象很多,最终就有可能消耗掉JVM中全部的内存。 最理想的状态其实就是这些生命周期相对短的对象,在它的生命周期结束之后,即使我们没有手动的调用remove 也可以被垃圾收集器回收掉。对于这种情况的解决办法就是使用弱引用来引用这些对象,这样哈希表中的键和值对象都能被垃圾回收。Java中提供了WeakHashMap来满足这一常见需求。

其实这里还有一个重大的使用场景就是jdk 里面大名鼎鼎的ThreadLocal, 接下来会写一篇文章分析,为什么ThreadLocal 里面的实现使用到弱引用

jdk8官方文档解析弱引用

原文  https://juejin.im/post/5d8b297e5188250b532eb013
正文到此结束
Loading...