java - Java ArrayList 迭代器中可能的内存泄漏

标签 java arraylist memory-leaks

我正在用 Java 开发一个简单的游戏,只是用作玩具程序来教我的学生一些技巧,但我遇到了一些问题。我的游戏使用了两个重复多次的 ArrayList。这些列表包含船舶发射的射弹以及这些射弹可以摧毁的目标。我需要不断验证屏幕中每个弹丸与每个目标之间的碰撞,以及与遍历这些列表相关的其他事项。我注意到当我的程序运行时,它的性能开始变得越来越差,所以我开始分析项目(我正在使用 NetBeans 分析器)以查找问题。

我发现的一件事是,使用 for each of Java 遍历列表(隐含地调用 iterator() 方法)大量内存开始被使用而不是被释放。

我写了下面的代码来测试这个。当我分析它时,ArrayList$itr 方法的内存消耗开始越来越大。该列表具有固定大小,所以我不明白为什么内存会继续增长,因为我有相同的数据结构。

看一下代码:

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

public class MemoryLeak {

    public static void main( String[] args ) {

        List<String> dummyData = new ArrayList<>();

        long quantity = 1000;
        long iterationTimeWithData = 60000;
        long iterationTimeEmpty = 10000;

        System.out.println( "adding data" );
        for ( int i = 0; i < quantity; i++ ) {
            dummyData.add( String.valueOf( Math.random() ) );
        }

        System.out.printf( "iterating through the list for %d seconds\n", iterationTimeWithData/1000 );
        long startTime = System.currentTimeMillis();
        while ( true ) {
            for ( String d : dummyData ) {}
            if ( System.currentTimeMillis() - startTime > iterationTimeWithData ) {
                break;
            }
        }

        System.out.println( "clear the list" );
        dummyData.clear();

        System.out.printf( "iterating through the empty list for %d seconds\n", iterationTimeEmpty/1000 );
        startTime = System.currentTimeMillis();
        while ( true ) {
            for ( String d : dummyData ) {}
            if ( System.currentTimeMillis() - startTime > iterationTimeEmpty ) {
                break;
            }
        }

    }

}

如果您运行代码并跟踪 ArrayList$itr,您会发现它的内存消耗在执行期间增长了很多。在我的游戏中,这种消耗是巨大的(超过 200 MB 并且还在不断增长)。使用正则 for,这不会发生。

我想知道这种行为是否正确,因为对我来说这很奇怪。

最佳答案

我试图通过实验证实 Louis Wasserman 的解释,事实上,我没有在上面的代码中观察到任何内存泄漏(使用 JDK 1.8.60)。我所做的是:

  • 将 main 方法的全部内容包装到 while(true) {...} 循环中,以便无限地填充、迭代和清除列表。
  • 观察jvisualvm中的内存,时不时强制GC。
  • 内存有时会增长到 100MB 左右,但在 GC 之后它总是下降到接近于零。

关于java - Java ArrayList 迭代器中可能的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32751181/

相关文章:

java - 使用 SAX 解析器解析 XML 数据并将其保存到 mysql localhost (JAVA) 的速度慢

c++ - 在带有 libstdc++ 的 Linux 上使用 -fsanitize=memory 和 clang

java - 如何在我的 Java 应用程序中查找内存泄漏

java - 为 API 方法建议一个更好的名称

java - 在Java中提取XML属性(ISBNDB)

java - 正确设置工具链后 Maven 构建错误

java - 无法转换为 int[][]

java - 如何在水平 ScrollView 中显示Arraylist项目?

java - 使用动态字符串引用 arraylist

ios - UIImage setImage 崩溃