关于SoftReference的使用

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)
原文地址:https://www.cnblogs.com/chaiwentao/p/4773247.html