前言
Java中的各种引用(强引用、软引用、弱引用、虚引用)(一)
Java中的各种引用(强引用、软引用、弱引用、虚引用)(二)
Java中的各种引用(强引用、软引用、弱引用、虚引用)(三)
这里介绍一下弱引用
实现
弱引用通过WeakReference对象来实现
WeakReference<byte[]> reference1 = new WeakReference<>(new byte[1024 * 1024 * 3]);
特点
弱引用指向的对象在两种情况下会被立即回收掉:
- 内存不足
- 触发GC
TestCode
JVM设置
-Xms20M -Xmx20M -XX:+PrintGC
Test1 内存充足的情况,不触发GC
code
package com.test.application;
import java.lang.ref.WeakReference;
public class WeakReferences {
public static void main(String[] args) throws InterruptedException {
WeakReference<byte[]> reference1 = new WeakReference<>(new byte[1024 * 1024 * 3]);
WeakReference<byte[]> reference2 = new WeakReference<>(new byte[1024 * 1024 * 4]);
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
Thread.sleep(1000);
byte[] big2 = new byte[3 * 1024 * 1024];
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
System.out.println(System.currentTimeMillis() + ": " + big2);
}
}
result
1604040001310:[B@140e19d
1604040001311:[B@17327b6
1604040002313:[B@140e19d
1604040002313:[B@17327b6
1604040002313: [B@14ae5a5
Test2 内存充足的情况下,触发GC
code
package com.test.application;
import java.lang.ref.WeakReference;
public class WeakReferences {
public static void main(String[] args) throws InterruptedException {
WeakReference<byte[]> reference1 = new WeakReference<>(new byte[1024 * 1024 * 3]);
WeakReference<byte[]> reference2 = new WeakReference<>(new byte[1024 * 1024 * 4]);
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
System.gc();
Thread.sleep(1000);
byte[] big2 = new byte[3 * 1024 * 1024];
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
System.out.println(System.currentTimeMillis() + ": " + big2);
}
}
result
1604040100543:[B@140e19d
1604040100543:[B@17327b6
[GC (System.gc()) 8721K->4852K(19712K), 0.0009327 secs]
[Full GC (System.gc()) 4852K->624K(19712K), 0.0030258 secs]
1604040101549:null
1604040101549:null
1604040101549: [B@14ae5a5
Test3 不触发GC,内存不足
code
package com.test.application;
import java.lang.ref.WeakReference;
public class WeakReferences {
public static void main(String[] args) throws InterruptedException {
WeakReference<byte[]> reference1 = new WeakReference<>(new byte[1024 * 1024 * 5]);
WeakReference<byte[]> reference2 = new WeakReference<>(new byte[1024 * 1024 * 6]);
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
Thread.sleep(1000);
byte[] big2 = new byte[12 * 1024 * 1024];
System.out.println(System.currentTimeMillis() + ":" + reference1.get());
System.out.println(System.currentTimeMillis() + ":" + reference2.get());
System.out.println(System.currentTimeMillis() + ": " + big2);
}
}
result
1604040233187:[B@140e19d
1604040233188:[B@17327b6
[GC (Allocation Failure) 13068K->11996K(19712K), 0.0011080 secs]
[GC (Allocation Failure) 11996K->11980K(19712K), 0.0022058 secs]
[Full GC (Allocation Failure) 11980K->661K(19712K), 0.0046475 secs]
1604040234198:null
1604040234198:null
1604040234198: [B@14ae5a5
结果分析
从结果上看,只要GC被触发了,无论是手动触发的还是因为内存不足JVM自动执行的,弱引用的对象一定会被回收。
结论
与软引用不同的是,只要触发GC就会回收弱引用对象,而软引用对象只有在内存不足的时候才会彻底回收。
如果一个对象是偶尔(很少)的使用,并且希望在使用时能获取到,但又不想影响此对象的垃圾收集,那么就可以用Weak Reference来记住此对象。