Java中四种引用类型:强引用,软引用,弱引用,虚引用

2020-08-13 11:40:39 浏览数 (1)

四种引用类型

  1. 强引用(StrongReference)
  2. 软引用(SoftReference)
  3. 弱引用(WeakReference)
  4. 虚引用 (PhantomReference)

强引用

类似Object obj = new Object()这类似的引用,强引用在程序代码中普遍存在,只要强引用在,垃圾搜集器永远不会搜集被引用的对象。也就是说,宁愿出现内存溢出(OutOfMemoryError),也不会回收这些对象

在IDEA中EditConfigiratons中设置参数:-Xms20m 设置堆内存大小为20M

执行如下代码:

代码语言:javascript复制
package com.example.reference;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示强引用
 * -Xmx20M
 */
public class StrongReference {

    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
        List<Byte[]> list = new ArrayList<>();
        for (int i = 0; i <5 ; i  ) {
            list.add(new Byte[_4MB]);
        }
        System.in.read();
    }

}

执行结果会异常Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

软引用

在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象

在IDEA中EditConfigiratons中设置参数:-Xmx20M -XX: PrintGCDetails

执行如下代码:

代码语言:javascript复制
package com.example.reference;

import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用
 * -XX: PrintGCDetails
 */
public class SoftReferenceTest {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i  ) {
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }
        System.out.println("-----------循环结束" list.size() "---------");
        for (SoftReference<byte[]> ref : list) {
            System.out.println(ref.get());
        }
    }

}

输出结果

代码语言:javascript复制
[B@2cdf8d8a
1
[B@30946e09
2
[B@5cb0d902
3
[GC (Allocation Failure) [PSYoungGen: 5434K->491K(6144K)] 17722K->13790K(19968K), 0.0042190 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Ergonomics) [PSYoungGen: 491K->0K(6144K)] [ParOldGen: 13298K->13724K(13824K)] 13790K->13724K(19968K), [Metaspace: 3273K->3273K(1056768K)], 0.0129237 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
[B@46fbb2c1
4
[Full GC (Ergonomics) [PSYoungGen: 4208K->4096K(6144K)] [ParOldGen: 13724K->13585K(13824K)] 17933K->17681K(19968K), [Metaspace: 3274K->3274K(1056768K)], 0.0155442 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 4096K->0K(6144K)] [ParOldGen: 13585K->1279K(8704K)] 17681K->1279K(14848K), [Metaspace: 3274K->3274K(1056768K)], 0.0130777 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
[B@1698c449
5
-----------循环结束5---------
null
null
null
null
[B@1698c449
Heap
 PSYoungGen      total 6144K, used 4377K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 5632K, 77% used [0x00000000ff980000,0x00000000ffdc6400,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 8704K, used 1279K [0x00000000fec00000, 0x00000000ff480000, 0x00000000ff980000)
  object space 8704K, 14% used [0x00000000fec00000,0x00000000fed3fcf0,0x00000000ff480000)
 Metaspace       used 3284K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 352K, capacity 388K, committed 512K, reserved 1048576K

我们发现使用SoftReference软引用之后,并没有内存溢出(OutOfMemoryError)异常,并且遍历list发现前四个byte数组为null了,通过输出结果及GC详细信息我们可以验证出,对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象

弱引用

弱引用也是用来描述非必需对象的,用java.lang.ref.WeakReference类来表示,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。

在IDEA中EditConfigiratons中设置参数:-Xmx20M -XX: PrintGCDetails

执行如下代码:

代码语言:javascript复制
package com.example.reference;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

public class WeakReferenceTest {

    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i  ) {
            WeakReference<byte[]> ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference<byte[]> w : list) {
                System.out.print(w.get() " ");
            }
            System.out.println();
        }
        System.out.println("-----------循环结束" list.size() "---------");
    }

}

输出结果:

代码语言:javascript复制
[B@2cdf8d8a 
[B@2cdf8d8a [B@30946e09 
[B@2cdf8d8a [B@30946e09 [B@5cb0d902 
[GC (Allocation Failure) [PSYoungGen: 5434K->507K(6144K)] 17722K->13757K(19968K), 0.0034897 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 507K->0K(6144K)] [ParOldGen: 13249K->1436K(13312K)] 13757K->1436K(19456K), [Metaspace: 3273K->3273K(1056768K)], 0.0109383 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
null null null [B@46fbb2c1 
null null null [B@46fbb2c1 [B@1698c449 
-----------循环结束5---------
Heap
 PSYoungGen      total 6144K, used 4321K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000)
  eden space 5632K, 76% used [0x00000000ff980000,0x00000000ffdb86e0,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 13312K, used 5532K [0x00000000fec00000, 0x00000000ff900000, 0x00000000ff980000)
  object space 13312K, 41% used [0x00000000fec00000,0x00000000ff1673e8,0x00000000ff900000)
 Metaspace       used 3282K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 352K, capacity 388K, committed 512K, reserved 1048576K

Process finished with exit code 0

虚引用

java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收

虚引用与软引用和弱引用的区别:虚引用必须和引用队列联合使用。

示例代码:

代码语言:javascript复制
Object object = new Object();
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue); 

0 人点赞