在ArrayList add()方法中创建新对象会导致内存泄漏。我能做些什么不同的事情?

时间:2013-08-23 08:35:16

标签: java object memory-leaks arraylist

我正在研究Java中类似扫雷的游戏,并注意到每当我重置电路板时都会发生内存泄漏。我在下面做了一个测试,发现每当我在ArrayList的add()方法中创建一个新对象时,只要我使用clear()方法,垃圾收集器就不会从内存中转储元素。以下是一些参考代码:

import java.util.ArrayList;
import java.util.Scanner;

public class MemLeakTest {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        ArrayList<PointlessObject> list = new ArrayList();

        String selection = "1";

        while(selection.equals("1")){
            System.out.print("Type 1 to run test:");
            selection = input.next();
            System.out.println();

            //begin test
            if(selection.equals("1")){
                for(int i = 0; i<100000; i++){
                    list.add(new PointlessObject());
                }
            }
            list.clear(); // ArrayList elements remained in memory
        }
    }

}

class PointlessObject{
    String text;

    public PointlessObject(){
        text = "Stuff";
    }
}

创建一个可以减少内存泄漏的长对象列表的更好的替代方法是什么?

3 个答案:

答案 0 :(得分:5)

进行以下测试:删除行

selection = input.next();
循环中的

。这将使它成为无限循环。如果你有内存泄漏,你会很快得到一个OutOfMemoryError,对吗?如果你没有得到,这意味着你没有任何内存泄漏。

您只是希望GC能够运行,但是当您认为它运行时它不会运行。它在必要时运行。

答案 1 :(得分:4)

此代码不应创建内存泄漏。您可以使用分析器查看内存的工作原理。使用JDK提供的优秀Visual VM(jvisualvm.exe)可以向您展示如何在您的应用程序中处理内存和GC。

首先,我将您的课程更新为在循环中自动运行。

package qwerky.sandbox;

import java.util.ArrayList;
import java.util.List;

public class MemLeakTest {

    public static void main(String[] args) throws Exception{

        List<PointlessObject> list = new ArrayList<PointlessObject>();

        while (true) {

            for(int i = 0; i<100000; i++){
                list.add(new PointlessObject());
            }

            Thread.sleep(1000);

            list.clear(); //ArrayList elements remained in memory

            Thread.sleep(1000);
        }
    }

}

class PointlessObject{
    String text;

    PointlessObject(){
        text = "Stuff";
    }
}

接下来我跑了它并附上了探查器。这是发生的事情。

jvisualvm profile

如你所见。内存使用量逐渐增加,但GC不时地启动和整理。当使用的堆达到大约35Mb时,这似乎每35秒发生一次。

您似乎担心GC在符合条件时不会立即清除 对象。这不是GC的工作方式。

答案 2 :(得分:-1)

您可以尝试在循环后将列表设置为null。