当前位置: 首页 > 知识库问答 >
问题:

FileWriter内存溢出

慕容文昌
2023-03-14

我想格式化和写入一个大的Map(1.785.530条目)的内容到一个文本文件。大约85%的条目被处理后,它变得非常慢,然后我得到一个OutOfMemoryExc0019

即使我:

  • 在我的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();
}

这里是抛出的异常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at sun.util.resources.TimeZoneNames.getContents(Unknown Source)
    at sun.util.resources.OpenListResourceBundle.loadLookup(Unknown Source)
    at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(Unknown Source)
    at sun.util.resources.OpenListResourceBundle.handleKeySet(Unknown Source)
    at java.util.ResourceBundle.containsKey(Unknown Source)
    at sun.util.locale.provider.LocaleResources.getTimeZoneNames(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameProviderImpl.getDisplayNameArray(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameProviderImpl.getDisplayName(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getName(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getObject(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter.getObject(Unknown Source)
    at sun.util.locale.provider.LocaleServiceProviderPool.getLocalizedObjectImpl(Unknown Source)
    at sun.util.locale.provider.LocaleServiceProviderPool.getLocalizedObject(Unknown Source)
    at sun.util.locale.provider.TimeZoneNameUtility.retrieveDisplayName(Unknown Source)
    at java.util.TimeZone.getDisplayName(Unknown Source)
    at java.util.Date.toString(Unknown Source)
    at java.lang.String.valueOf(Unknown Source)
    at FileMerger.writeOutputFile(FileMerger.java:95)
    at FileMerger.main(FileMerger.java:26)

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

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

int accesses = 43267;

for (int i = 0; i < 1785530; i++) {
    Date date = new Date(i);
    accessesPerSecondMap.put(date, accesses);
}

为了跟踪内存使用情况,我在for循环中添加了以下内容:

...
    int count = 100000;
    for (Date date : accessesPerSecondMap.keySet()) {

        if (count == 100000) {
            count = 0;
            printOutMemoryUsage();
        }
        count++;
...

private void printOutMemoryUsage() {
    Runtime runtime = Runtime.getRuntime();

    NumberFormat format = NumberFormat.getInstance();

    StringBuilder sb = new StringBuilder();
    long maxMemory = runtime.maxMemory();
    long allocatedMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();

    sb.append("free memory: " + format.format(freeMemory / 1024) + " ");
    sb.append("allocated memory: " + format.format(allocatedMemory / 1024)
            + " ");
    sb.append("max memory: " + format.format(maxMemory / 1024) + " ");
    sb.append("total free memory: "
            + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024)
            + "<br/>");
    System.out.println(sb);
}

当我不增加堆空间时,我得到了这个输出:

free memory: 28.868 allocated memory: 156.792 max memory: 253.440 total free memory: 125.516
free memory: 89.847 allocated memory: 253.440 max memory: 253.440 total free memory: 89.847
free memory: 87.796 allocated memory: 253.440 max memory: 253.440 total free memory: 87.796
free memory: 89.758 allocated memory: 253.440 max memory: 253.440 total free memory: 89.758
free memory: 32.478 allocated memory: 253.440 max memory: 253.440 total free memory: 32.478
free memory: 35.182 allocated memory: 253.440 max memory: 253.440 total free memory: 35.182
free memory: 37.269 allocated memory: 253.440 max memory: 253.440 total free memory: 37.269
free memory: 45.165 allocated memory: 253.440 max memory: 253.440 total free memory: 45.165
free memory: 42.943 allocated memory: 253.440 max memory: 253.440 total free memory: 42.943
free memory: 32.055 allocated memory: 253.440 max memory: 253.440 total free memory: 32.055
free memory: 13.053 allocated memory: 253.440 max memory: 253.440 total free memory: 13.053
free memory: 14.281 allocated memory: 253.440 max memory: 253.440 total free memory: 14.281
free memory: 12.797 allocated memory: 253.440 max memory: 253.440 total free memory: 12.797
free memory: 1.973 allocated memory: 253.440 max memory: 253.440 total free memory: 1.973
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

随着增加的堆空间-Xms512m-Xmx1230mi get:

free memory: 372.630 allocated memory: 506.816 max memory: 1.217.536 total free memory: 1.083.350
free memory: 329.031 allocated memory: 506.816 max memory: 1.217.536 total free memory: 1.039.751
free memory: 273.121 allocated memory: 506.816 max memory: 1.217.536 total free memory: 983.841
free memory: 333.700 allocated memory: 506.816 max memory: 1.217.536 total free memory: 1.044.420
free memory: 276.392 allocated memory: 506.816 max memory: 1.217.536 total free memory: 987.112
free memory: 220.482 allocated memory: 506.816 max memory: 1.217.536 total free memory: 931.202
free memory: 279.896 allocated memory: 506.816 max memory: 1.217.536 total free memory: 990.616
free memory: 223.986 allocated memory: 506.816 max memory: 1.217.536 total free memory: 934.706
free memory: 284.565 allocated memory: 506.816 max memory: 1.217.536 total free memory: 995.285
free memory: 228.654 allocated memory: 506.816 max memory: 1.217.536 total free memory: 939.374
free memory: 169.949 allocated memory: 506.816 max memory: 1.217.536 total free memory: 880.669
free memory: 230.528 allocated memory: 506.816 max memory: 1.217.536 total free memory: 941.248
free memory: 174.618 allocated memory: 506.816 max memory: 1.217.536 total free memory: 885.338
free memory: 235.197 allocated memory: 506.816 max memory: 1.217.536 total free memory: 945.917
free memory: 179.287 allocated memory: 506.816 max memory: 1.217.536 total free memory: 890.007
free memory: 123.376 allocated memory: 506.816 max memory: 1.217.536 total free memory: 834.096
free memory: 183.956 allocated memory: 506.816 max memory: 1.217.536 total free memory: 894.676
free memory: 128.046 allocated memory: 506.816 max memory: 1.217.536 total free memory: 838.766
FileMerger main method finished

共有3个答案

卫深
2023-03-14

在月食中。。。在工具栏上单击Run-

-Xms512M -Xmx1524M // This may be XS512M or Xx1524M.

转到参数部分。这将允许更大的文件以更大的堆空间更平稳地运行,正如@AliGajani在评论中提到的那样。

酆恩
2023-03-14
  1. 试着写例如第一个10000条记录。关闭写入器,然后再次创建它,并尝试追加另外10000条记录,以此类推。
  2. 尝试使用StringBuilder在每个循环迭代中构建一个字符串,并在循环迭代中调用写()一次。
林英朗
2023-03-14

一般有两种方法可以消除这个错误

java.lang.OutOfMemoryError: Java heap space
  1. 允许JVM使用更多内存

使用-Xmx JVM参数,可以设置堆大小。在命令行上使用java-Xms-Xmx。

 类似资料:
  • JNIEXPORT jint JNICALL Java_nc_mes_pub_hardware_PCI1761_readChanel(JNIEnv*,jobject,jint channel){ }

  • 在Scrapy中,类似Requests, Response及Items的对象具有有限的生命周期: 他们被创建,使用,最后被销毁。 这些对象中,Request的生命周期应该是最长的,其会在调度队列(Scheduler queue)中一直等待,直到被处理。 更多内容请参考 架构概览 。 由于这些Scrapy对象拥有很长的生命,因此将这些对象存储在内存而没有正确释放的危险总是存在。 而这导致了所谓的”内

  • 内存溢出 内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。 内存泄漏通常情况下只能由获得程序源代码的程序员才能分析出来, 也是一个比较难以排查的问题。所有需要在开发前知道一些规范 内存溢出一直向一个 属性/变量 写数据 , 写入超过内存最大限

  • 一、内存溢出 一种程序运行出现的错误。 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误。 二、内存泄漏 占用的内存没有及时释放。 内存泄露积累多了就容易导致内存溢出。 常见的内存泄露: 意外的全局变量。 没有及时清理的计时器或回调函数。 闭包 // 1. 内存溢出 var obj = {} for (var i = 0; i < 10000; i++) { obj[i] =

  • 本文向大家介绍Android 内存溢出和内存泄漏的问题,包括了Android 内存溢出和内存泄漏的问题的使用技巧和注意事项,需要的朋友参考一下 Android 内存溢出和内存泄漏的问题 在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。 内存溢出 (OOM)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;

  • 本文向大家介绍内存泄漏和内存溢出有什么区别相关面试题,主要包含被问及内存泄漏和内存溢出有什么区别时的应答技巧和注意事项,需要的朋友参考一下 内存泄漏是分配的内存无法释放,导致一直占用内存空间,最终可能引发内存溢出 内存溢出是申请或使用内存超出可以分配的内存时(例如往一个整形空间存放长整形的数据) 参考文章