我正在研究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";
}
}
创建一个可以减少内存泄漏的长对象列表的更好的替代方法是什么?
答案 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";
}
}
接下来我跑了它并附上了探查器。这是发生的事情。
如你所见。内存使用量逐渐增加,但GC不时地启动和整理。当使用的堆达到大约35Mb时,这似乎每35秒发生一次。
您似乎担心GC在符合条件时不会立即清除 对象。这不是GC的工作方式。
答案 2 :(得分:-1)
您可以尝试在循环后将列表设置为null。