Java 文件写入程序内存不足

Java 文件写入程序内存不足,java,out-of-memory,filewriter,Java,Out Of Memory,Filewriter,我想格式化一个大的映射(1.785.530条目的内容)并将其写入一个文本文件。在处理了大约85%的条目之后,它变得非常慢,然后我得到了一个OutOfMemoryException 即使我: 在myFileWriter上定期调用flush()或close() 使用BufferedWriter 在写入文件之前,将每行写入StringBuffer 这是我的代码: private static final TreeMap<Date, Integer> accessesPerSecondM

我想格式化一个大的
映射
(1.785.530条目的内容)并将其写入一个文本文件。在处理了大约85%的条目之后,它变得非常慢,然后我得到了一个
OutOfMemoryException

即使我:

  • 在my
    FileWriter上定期调用
    flush()
    close()
  • 使用
    BufferedWriter
  • 在写入文件之前,将每行写入
    StringBuffer
这是我的代码:

private static final TreeMap<Date, Integer> accessesPerSecondMap = new    
    TreeMap<>();

...

private static void writeOutputFile() throws IOException {
    FileWriter writer = new FileWriter(FILENAME_OUTPUT);

    writer.write("Date");
    writer.write(',');
    writer.write("Request Count");
    writer.write('\n');

    for (Date date : accessesPerSecondMap.keySet()) {

        // first and last date are not precise so do not write it in the
        // file
        if (date == accessesPerSecondMap.firstKey()
                || date == accessesPerSecondMap.lastKey()) {
            continue;
        }

        writer.write(String.valueOf(date));
        System.out.println("FileMerger wrote: " + String.valueOf(date));
        writer.write(',');
        writer.write(String.valueOf(accessesPerSecondMap.get(date)));
        writer.write('\n');

    }

    writer.flush();
    writer.close();
}
增加堆空间对我来说是可行的,但在我看来并不是一个真正令人满意的解决方案。再过几天,我将不得不写两倍大的文件;希望空间也够他们用

我正在Windows上运行Java1.8.045。上面的代码是真正的代码,也是唯一正在运行的代码。出于测试目的,我使用以下代码填充
TreeMap

int accesses = 43267;

for (int i = 0; i < 1785530; i++) {
    Date date = new Date(i);
    accessesPerSecondMap.put(date, accesses);
}
随着heapspace
-Xms512m-Xmx1230m的增加,我得到:

可用内存:372.630分配内存:506.816最大内存:1.217.536总可用内存:1.083.350
可用内存:329.031已分配内存:506.816最大内存:1.217.536总可用内存:1.039.751
可用内存:273.121分配内存:506.816最大内存:1.217.536总可用内存:983.841
可用内存:333.700已分配内存:506.816最大内存:1.217.536总可用内存:1.044.420
可用内存:276.392分配内存:506.816最大内存:1.217.536总可用内存:987.112
可用内存:220.482已分配内存:506.816最大内存:1.217.536总可用内存:931.202
可用内存:279.896已分配内存:506.816最大内存:1.217.536总可用内存:990.616
可用内存:223.986已分配内存:506.816最大内存:1.217.536总可用内存:934.706
可用内存:284.565分配内存:506.816最大内存:1.217.536总可用内存:995.285
可用内存:228.654分配内存:506.816最大内存:1.217.536总可用内存:939.374
可用内存:169.949分配内存:506.816最大内存:1.217.536总可用内存:880.669
可用内存:230.528已分配内存:506.816最大内存:1.217.536总可用内存:941.248
可用内存:174.618分配内存:506.816最大内存:1.217.536总可用内存:885.338
可用内存:235.197已分配内存:506.816最大内存:1.217.536总可用内存:945.917
可用内存:179.287分配内存:506.816最大内存:1.217.536总可用内存:890.007
可用内存:123.376已分配内存:506.816最大内存:1.217.536总可用内存:834.096
可用内存:183.956分配内存:506.816最大内存:1.217.536总可用内存:894.676
可用内存:128.046已分配内存:506.816最大内存:1.217.536总可用内存:838.766
文件合并主方法已完成

在eclipse中…在工具栏上单击
运行->运行配置
找到您正在运行的类的名称,选择它,单击
参数选项卡
,然后添加:

-Xms512M -Xmx1524M // This may be XS512M or Xx1524M.
转到参数部分。这将允许更大的文件以更大的堆空间更平稳地运行,如注释中提到的@AliGajani

  • 例如,试着写前10000条记录。关闭writer,然后再次创建它并尝试追加10000条记录,以此类推
  • 尝试使用StringBuilder在每个循环迭代中构建一个字符串,并在循环迭代中调用write()

  • 通常有两种方法可以消除此错误

    java.lang.OutOfMemoryError: Java heap space
    
  • 允许JVM使用更多内存
  • 使用-Xmx JVM参数,可以设置堆大小。在命令行上使用java-Xms-Xmx

  • 使用 Eclipse内存分析器是Eclipse基金会的一个工具,用来分析java堆转储。它有助于发现类加载器泄漏和内存泄漏,并有助于最大限度地减少内存消耗。您可以使用MAT分析承载数百万对象的堆转储,还可以帮助您提取内存泄漏的嫌疑人

  • 尝试放置
    writer.flush()在for循环中。通过这样做,我相信你的缓冲将是自由的,而不是变得沉重

    将数据写入文件时,写入程序将保留数据的引用,因此GC无法回收内存。因此,您应该使用writer.reset()来释放

    您可以很容易地从Eclipse增加堆空间您是否尝试过定期刷新?您可以尝试通过增加Java默认堆大小来修复此问题,但您可能仍然会遇到此错误。因此,您应该尝试以这样的方式实现您的程序,以便它能够防止内存泄漏,并且不会抛出OfMemoryError。我在“重复”问题或其任何答案中完全看不到与此问题相关的任何内容。如果任何重复投票的人知道这两个问题的答案都是一样的,请把它贴出来,而不是留给自己。。。(更具体地说,另一个问题的答案涉及时间效率,减少系统调用和磁盘写入。在这个问题中,有一个问题导致堆内存耗尽,如OP的问题标题、问题中的单词、发布的堆栈跟踪和问题标记所示。因此,如果答案相同,则无法(从阅读链接问题的答案可以看出。)然后,在VM初始化过程中出现错误,无法为1560576KB对象保留足够的空间。heapI建议将我的答案和@Tomek的答案结合使用。使用新堆大小写入最大允许值,然后关闭写入程序。然后重新打开并再次执行。如果您的问题确实位于没有eno的区域ugh JVM内存尝试使用64位JVM,如果OP或任何查看本文以供将来参考的人没有64位JVM(我知道不太可能),它将允许您使用超过1,5GB的内存(如果您的计算机和操作系统架构支持这一点),他们该怎么办?我知道答案,但我建议你把它作为一个答案贴出来。如果你使用32位操作系统,试着少用一点(大约1)
    java.lang.OutOfMemoryError: Java heap space