SoftReference一般可以用来创建缓存的,缓存我们经常使用,例如:我们在浏览器中浏览了一个网页后,点击跳转到新的网页,我们想回去看之前的网页,一般是点击回退按钮,那么这个时候之前的网页一般就是放在缓存中了。如果网页太多,有时候就会造成回不去的情形,这说明如果内存不够用了,就删除了这些缓存。
类似这种情形就可以用SoftReference来实现,SoftReference的GC机制是这样的,如果内存够用,它不会被GC,但如果内存不够用,且内存中的对象只被一个SoftRerence类型的引用指向的话(一个对象也可以被一个强引用和软引用同时指向),那么它就会被GC。
那么这个时候有一个疑问,如果用SoftReference引用指向的对象内部有强引用指向的复杂对象,那么当内存不足时的会如何处理呢?
看下面代码:
1 import java.lang.ref.*; 2 3 public class Test { 4 5 static final int MB = 1024 * 1024; 6 7 byte[] b = new byte[4 * MB]; 8 9 public static void main(String[] args) { 10 11 SoftReference<Test> test = new SoftReference<Test>(new Test()); 12 // Test test = new Test(); 13 byte[] c = new byte[4 * MB]; 14 } 15 }
我们调整运行参数:
则个运行结果是:
1 [GC [PSYoungGen: 313K->288K(2368K)] 4409K->4384K(7872K), 0.0006568 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 2 [GC [PSYoungGen: 288K->288K(2368K)] 4384K->4384K(7872K), 0.0002187 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 3 [Full GC [PSYoungGen: 288K->0K(2368K)] [PSOldGen: 4096K->4293K(5504K)] 4384K->4293K(7872K) [PSPermGen: 2952K->2952K(21248K)], 0.0029254 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 4 [GC [PSYoungGen: 0K->0K(2368K)] 4293K->4293K(7872K), 0.0000939 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 5 [Full GC [PSYoungGen: 0K->0K(2368K)] [PSOldGen: 4293K->192K(4544K)] 4293K->192K(6912K) [PSPermGen: 2952K->2949K(21248K)], 0.0033466 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 6 Heap 7 PSYoungGen total 2368K, used 41K [0x000000000aed0000, 0x000000000b170000, 0x000000000b170000) 8 eden space 2048K, 2% used [0x000000000aed0000,0x000000000aeda478,0x000000000b0d0000) 9 from space 320K, 0% used [0x000000000b0d0000,0x000000000b0d0000,0x000000000b120000) 10 to space 320K, 0% used [0x000000000b120000,0x000000000b120000,0x000000000b170000) 11 PSOldGen total 4544K, used 4288K [0x000000000a970000, 0x000000000ade0000, 0x000000000aed0000) 12 object space 4544K, 94% used [0x000000000a970000,0x000000000ada00c8,0x000000000ade0000) 13 PSPermGen total 21248K, used 2989K [0x0000000005570000, 0x0000000006a30000, 0x000000000a970000) 14 object space 21248K, 14% used [0x0000000005570000,0x000000000585b6f8,0x0000000006a30000)
虚拟机堆区大小被限制在7MB,然后分配了一个含有4MB的SoftReference类,然后当继续申请4MB堆区时,JVM就会回收掉test所指向的对象。
如果按下面这样去写代码,就会报出OutOfMemoryError。
import java.lang.ref.*; public class Test { static final int MB = 1024 * 1024; byte[] b = new byte[4 * MB]; public static void main(String[] args) { //SoftReference<Test> test = new SoftReference<Test>(new Test()); Test test = new Test(); byte[] c = new byte[4 * MB]; } }
内纯回收日志:
[GC [PSYoungGen: 313K->272K(2368K)] 4409K->4368K(7872K), 0.0006490 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [PSYoungGen: 272K->288K(2368K)] 4368K->4392K(7872K), 0.0001820 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 288K->0K(2368K)] [PSOldGen: 4104K->4296K(5504K)] 4392K->4296K(7872K) [PSPermGen: 2952K->2952K(21248K)], 0.0028587 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [PSYoungGen: 0K->0K(2368K)] 4296K->4296K(7872K), 0.0001105 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC [PSYoungGen: 0K->0K(2368K)] [PSOldGen: 4296K->4288K(5504K)] 4296K->4288K(7872K) [PSPermGen: 2952K->2948K(21248K)], 0.0036936 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Test.main(Test.java:13) Heap PSYoungGen total 2368K, used 82K [0x000000000af70000, 0x000000000b210000, 0x000000000b210000) eden space 2048K, 4% used [0x000000000af70000,0x000000000af84868,0x000000000b170000) from space 320K, 0% used [0x000000000b170000,0x000000000b170000,0x000000000b1c0000) to space 320K, 0% used [0x000000000b1c0000,0x000000000b1c0000,0x000000000b210000) PSOldGen total 5504K, used 4288K [0x000000000aa10000, 0x000000000af70000, 0x000000000af70000) object space 5504K, 77% used [0x000000000aa10000,0x000000000ae400a8,0x000000000af70000) PSPermGen total 21248K, used 2990K [0x0000000005610000, 0x0000000006ad0000, 0x000000000aa10000) object space 21248K, 14% used [0x0000000005610000,0x00000000058fbb60,0x0000000006ad0000)