Java弱引用详解

  强引用就是指在程序代码之中普遍存在的,类似“Object obj=new Object()”这类的引
用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。  
  弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的
对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,
都会回收掉只被弱引用关联的对象
弱引用和强引用看似是两个不同的关系,但是实际情况中只要一个对象只要被强引用关联,则不管他是否被弱引用关联、还是被软引用关联,这个对象只会表现出强引用的特性
看代码:

public class Test {
    //A、B是两个最普通的POJO
    public static void main(String[] args) throws InterruptedException {
        B b1 = new B();
        A a1 = new A("a1",b1);
        WeakReference weakReference2 = new WeakReference(a2);
        Thread.sleep(20000);
        System.out.println("回收结束  weakReference1:"+ weakReference1.get());
    }
}

Java弱引用详解_第1张图片
采用jconsole观察内存变化,手动触发gc之后,可以看到输出结果中弱引用关联的的A类的实例对象还没有被释放,这就证明了上句中当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。

但是一旦代码稍稍修改一下就可以看出弱引用的作用了:

public class Test {

    public static void main(String[] args) throws InterruptedException {
        B b1 = new B();
        A a1 = new A("a1",b1);
        WeakReference weakReference1 = new WeakReference(a1);
        //消除a1的强引用
        a1 = null;
        Thread.sleep(20000);
        System.out.println("回收结束  weakReference1:"+ weakReference1.get());
    }
}

Java弱引用详解_第2张图片
可以看到JVM进行了GC之后,输出结果中弱引用关联的A类的实例对象被释放,这就证明了上句中当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。

以上仅仅是介绍了什么是弱引用但是我们依旧不知道这种引用有什么作用,那么我就给大家介绍一下ThreadLocal中弱引用的使用:

 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

可以看出来ThreadLocal中value是存储在ThreadLocalMap中的,众所周知的是ThreadLocalMap是有多个Entry组成的,

static class ThreadLocalMap {

        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

可以看出来Entry是继承自WeakReference,也就是说一个ThreadLocalMap发生了哈希冲突的时候原有Entry被替换之后,即不存在强引用指向原来的Entry,因此该Entry在下次GC的时候就会被回收,这大大减少了频繁的哈希冲突之后产生的垃圾碎片。以上ThreadLocalMap的源码是基于JDK1.8的,有兴趣的同学可以自己去看看源码,ThreadLocalMap处理哈希冲突的方式是开放定址法,不是传统的链路法,明白这个看起来就简单很多

你可能感兴趣的:(JVM)