没有垃圾收集器有时间收集 SoftReference,总是 OutOfMemoryError

No garbage collector has time to collect SoftReference, always OutOfMemoryError

尝试了所有垃圾收集器,一百万种不同的设置组合。 但结果总是一样的——OutOfMemoryError。

谁能说出哪个垃圾收集器能够及时删除软引用引用的对象

下面的示例模拟器代码

package com;

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

class SoftReferenceCollector {

    private static class Data {
        public long[] l = new long[100];
    }

    private List<SoftReference<Data>> list = new ArrayList<>();

    public void startFillCollection(int durationInSec) {
        long i = 0;

        long start = System.currentTimeMillis();
        long end = start + durationInSec * 1000;
        while (System.currentTimeMillis() < end) {
            list.add(new SoftReference<>(new Data()));
            ++i;
            if (i % 10000 == 0) {
                sleep(1);
                if (i % 1_000_000 == 0)
                    sleep(1000);
            }
        }
    }

    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ignored) {
        }
    }
}


public class Main6 {
    public static void main(String[] args) {
        SoftReferenceCollector softReferenceCollector = new SoftReferenceCollector();
        softReferenceCollector.startFillCollection(11240);

    }
}

ReferentsSoftReference 引用的对象)在抛出 OOO 异常之前被 GC 清除。

但是没有被垃圾收集的是 SoftReference 对象本身。它们也是对象,它们消耗堆内存。它们都被列表保存在内存中。 GC只清除它们指向的对象,即referent.

运行 你的 JVM -XX:+HeapDumpOnOutOfMemoryError。此标志将在 OOO 之前转储堆,以便您稍后可以对其进行分析。您可以使用 Eclipse 内存分析器。

您也可以尝试 -XX:+PrintReferenceGC 标志,它会打印一些关于清理这些类型的引用在 gc 周期中花费的时间的信息。