Java - 未引用的数组仍然占用内存

Java - unreferenced arrays still take up memory

我目前正在优化我的应用程序,我注意到它占用了将近 1 GB 的 RAM。我做了一些分析并发现了问题: 我通过在我制作的纹理 class 中创建保存像素数据的 int 数组来分配大量内存。 但这让我很困惑,因为当创建一个新数组时,旧数组不再被使用,并且在任何地方都没有引用它。

我写了一个重现这个问题的测试程序:

public class Main {

    static class ArrayHolder {
        int[] array;

        void init() {
            array = null;
            array = new int[4000];
        }
    }

    public static void main(String[] args) {
        ArrayHolder holder = new ArrayHolder();
        for (int i = 0; i < 1000000; i++) {
            holder.init();
        }
        System.out.println(holder.array.length);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

当我 运行 编写此代码时,程序会占用 600 兆字节的 RAM。我不明白为什么,因为在 ArrayHolder 中调用 init() 方法时,数组字段被设置为新数组并且对旧数组的引用丢失了。 那岂不是不再占用space了? 很抱歉,如果这是一个菜鸟问题,但有人可以解释为什么会这样以及我在这里做错了什么吗?

仅仅因为您的对象没有引用并不意味着它不会占用任何内存。 GC 必须 运行,然后才会从内存中 "removed"。您可以让没有引用的对象在内存中占用 space。检查 GC 是否有 运行,如果没有显式调用它(虽然不是一个好主意)。另外,我建议你看看你是否真的对你的对象有一些强引用。

您使用 System.gc() 显式调用 GC。

您可以添加 JVM 参数,例如 '-XX:+PrintGCDetails' 来检查 GC 是否有 运行。

array 是对 Java 中数组的 引用 。在这方面,它们就像派生自 java.lang.Object 的任何其他常规对象一样。一旦不再有对数组的引用,它就会被安排进行垃圾回收,这不需要立即发生。

这种释放内存的延迟不太可能给您带来麻烦:垃圾收集器会在需要时收集未引用的对象。

注意即使垃圾收集器做了运行那么仍然不能保证进程会把内存交还给OS,或者 OS 将从进程中夺回内存。