首页 > 解决方案 > 为什么Java WeakReference会出现OutOfMemoryError?

问题描述

我知道弱引用很容易被GC。和

弱引用对象,不会阻止它们的引用对象被最终化、最终化,然后被回收。弱引用最常用于实现规范化映射。假设垃圾收集器在某个时间点确定一个对象是弱可达的。那时,它将原子地清除对该对象的所有弱引用以及对通过强引用和软引用链可以访问该对象的任何其他弱可达对象的所有弱引用。同时它将声明所有以前的弱可达对象都是可终结的。在同一时间或稍后的某个时间,它会将那些在引用队列中注册的新清除的弱引用排入队列。

https://docs.oracle.com/javase/8/docs/api/java/lang/ref/WeakReference.html

但是,下面的代码会OOM。</p>

//-XX:+HeapDumpOnOutOfMemoryError -Xmx20m -Xms20m -XX:+PrintGCDetails
@Test(expected = OutOfMemoryError.class)
public void testOne() {
    WeakReference<List<char[]>> holder = new WeakReference<>(Lists.newLinkedList());

    for (int i = 0; i < 20; i++) {
        holder.get().add(new char[_512_KB]);
        System.out.println("i = " + i + "; size = " + holder.get().size());
    }
}

打印信息是

> [GC (Allocation Failure) [PSYoungGen: 5632K->496K(6144K)] 5632K->1184K(19968K), 0.0022957 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
i = 0; size = 1
i = 1; size = 2
i = 2; size = 3
i = 3; size = 4
[GC (Allocation Failure) [PSYoungGen: 5497K->496K(6144K)] 6185K->5477K(19968K), 0.0027950 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
i = 4; size = 5
i = 5; size = 6
i = 6; size = 7
i = 7; size = 8
i = 8; size = 9
[GC (Allocation Failure) [PSYoungGen: 5727K->496K(6144K)] 10709K->10630K(19968K), 0.0027462 secs] [Times: user=0.02 sys=0.01, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 496K->0K(6144K)] [ParOldGen: 10134K->9942K(13824K)] 10630K->9942K(19968K), [Metaspace: 4789K->4789K(1056768K)], 0.0089587 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] 
i = 9; size = 10
i = 10; size = 11
i = 11; size = 12
i = 12; size = 13
i = 13; size = 14
[Full GC (Ergonomics) [PSYoungGen: 5344K->2048K(6144K)] [ParOldGen: 9942K->13014K(13824K)] 15286K->15062K(19968K), [Metaspace: 4789K->4789K(1056768K)], 0.0067482 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 
i = 14; size = 15
i = 15; size = 16
i = 16; size = 17
[Full GC (Ergonomics) [PSYoungGen: 5230K->5120K(6144K)] [ParOldGen: 13014K->13014K(13824K)] 18244K->18134K(19968K), [Metaspace: 4789K->4789K(1056768K)], 0.0030614 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 5120K->5120K(6144K)] [ParOldGen: 13014K->12955K(13824K)] 18134K->18075K(19968K), [Metaspace: 4789K->4786K(1056768K)], 0.0093199 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid46130.hprof ...
Heap dump file created [19571071 bytes in 0.123 secs]

GC 被调用。

标签: java

解决方案


谢谢@matt。holder.get().add(new char[_512_KB]);导致此案。

更好的代码是:

    //-XX:+HeapDumpOnOutOfMemoryError -Xmx20m -Xms20m -XX:+PrintGCDetails
@Test(expected = OutOfMemoryError.class)
public void testOne() {
    WeakReference<List<char[]>> holder = new WeakReference<>(Lists.newLinkedList());

    for (int i = 0; i < 20; i++) {
        char[] chs = new char[_512_KB];
        holder.get().add(chs);
        System.out.println("i = " + i + "; size = " + holder.get().size());
    }
}

推荐阅读