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

时间:2017-04-20 08:53:10

标签: java arrays memory ram allocation

我目前正致力于优化我的应用程序,我注意到它占用了近1 GB的RAM。我做了一些分析,发现了问题: 我通过在我制作的纹理类中创建保存像素数据的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()方法时,数组字段被设置为新数组,并且对旧数组的引用将丢失。 这不意味着它不再占用空间吗? 我很抱歉,如果这是一个愚蠢的问题,但有人能解释为什么会这样,我在这里做错了吗?

2 个答案:

答案 0 :(得分:2)

仅仅因为你的对象没有引用并不意味着它不会占用任何内存。 GC必须运行,然后才会被删除&#34;从记忆里。你可以在内存中没有引用的对象占用空间。检查GC是否已运行,如果没有明确调用(尽管不是一个好主意)。另外,我建议你找一下你对象的强引用。

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

您可以添加JVM参数,例如&#39; -XX:+ PrintGCDetails&#39;检查GC是否已运行。

答案 1 :(得分:1)

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

释放内存的这种延迟不太可能导致您遇到麻烦:垃圾收集器会在需要时收集未提供的对象。

请注意,即使垃圾收集器 运行,仍然无法保证进程将内存返回给操作系统,否则操作系统将从进程中获取内存。 / p>