-2

我做了这个例子,通过 -Xmx64m

我知道这个程序不会泄漏内存(或不会?)。但我不知道垃圾收集器是如何做到的,因为每次我创建一个新的双数组。

该程序是否可能存在内存泄漏?因为我每次都会创建一个新的双打数组?

垃圾收集器在哪里收集新的 double ?

public class TestLeakMemory {

private static float total;

public static void main(String[] args) throws InterruptedException {
    long currtime = System.currentTimeMillis();
    long timeElapsed = 0;
    long lastTime = 0;
    long count = 0;
    while (timeElapsed < 6000000) {
        //Thread.sleep(100);
        count++;

        double arr1[] = new double[200000];
        double arr2[] = new double[200000];
        double arr3[] = new double[200000];
        float doSomething = doSomething(arr1, arr2, arr3);

        total += doSomething;

        timeElapsed = System.currentTimeMillis() - currtime;

        if (System.currentTimeMillis() - lastTime > 3000) {
            System.out.println("totalMemory: " + Runtime.getRuntime().totalMemory() + ", freeMemory: " + Runtime.getRuntime().freeMemory() + ", count: " + count);
            lastTime = System.currentTimeMillis();
        }
    }

    System.out.println(total);
}

private static float doSomething(double[] arr1, double[] arr2, double[] arr3) {
    float total = 0;
    for (double d : arr1) {
        total += d;
    }
    for (double d : arr2) {
        total += d;
    }
    for (double d : arr3) {
        total += d;
    }

    return total;
}

}

4

1 回答 1

3

这里没有内存泄漏。

仅仅创建一个对象或数组然后将其引用“放在地板上”不会造成内存泄漏。垃圾收集器会发现对象/数组不再可达并删除它。这不会立即发生,但会在您的应用程序内存不足之前发生。

在 Java 中,当对象仍然可以访问但不应该访问时,就会发生内存泄漏。GC 不知道这些对象不会被再次使用,只是保留它们。

例如,如果您将所有这些数组的列表保存在变量ArrayList引用的 a 中。static收集器无法知道您的程序是否(真的)需要这些对象。因此,由于它们是可访问的,因此可以保留它们。如果你继续这样做,你就会耗尽内存。


如果您使用该程序获得 OOME,则不是由于内存泄漏。这将是由于堆太小。但我认为这不太可能:200,000 x 3 x 8 字节小于 5 兆字节,而您将堆的上限设置为 64 兆字节。

可以重用这些数组来减少对象创建/删除的流失,但尚不清楚这是否值得。您的示例代码不代表真实的应用程序。

于 2018-11-05T00:03:48.027 回答