1

我有这样的情况:我从 CSV 文件中读取行并将它们放入List<String>. 完成后,根据特殊逻辑对行进行解析,并将其部分作为键放入多个HashMap<String, Integer>. 然后列表记录被清除。其实我尝试了几种方法:

records.clear();
records = null;
records = new ArrayList<String>();

但似乎无论如何都没有释放内存(通过使用分析器和简单的打印到控制台检查它)。由于读取文件和进一步解析的这种迭代重复了几次,有一次我得到一个OutOfMemoryError.

有人可以在这里提出任何解决方案吗?Java有可能解决它吗?或者垃圾收集器的字符串池不可忽略?也许像 C++ 这样的其他语言更合适?

谢谢你。

4

6 回答 6

3

你说:

完成后,根据特殊逻辑对行进行解析,并将其部分作为键放入若干个HashMap中。

如果您通过类似 String.substring 的方式获取这些部分,则该子字符串不是新副本,它实际上是指向原始字符串,并且知道包含子字符串的开始和索引。

因此,只要这些子字符串中的任何一个存在,原始字符串就不会被垃圾收集。如果这些子字符串被传递到系统的其他部分,那么清除您的集合将无济于事。

您需要确保创建了一个全新的字符串,例如:

new String( myString.substring( 1, 5 ) );

这是一个看起来不错的链接(谷歌搜索“原始的字符串子字符串点”)。 http://javarevisited.blogspot.com/2011/10/how-substring-in-java-works.html

虽然显然后来的 JDK 1.7 版本已经根据这个解决了这个问题: 字符串类的 subString() 函数是如何工作的

于 2013-06-05T17:15:10.597 回答
1

我们需要更多代码才能查看您是否在某处有“内存泄漏”。

您是否考虑过在列表中存储更少的行而不是读取列表中的整个文件?此外,您可以尝试一起取消中间结构。

  • 读取 100 行并将其添加到列表中
  • 遍历、解析并添加到 hashmaps。
  • 清晰的列表

您可以增加堆大小,但如果您没有发现泄漏,如果您遇到非常大的文件大小,这可能会导致另一个异常。很好,dystroy 指出了这一点。

增加堆的说明位于: 增加 Java 中的堆大小

例子:java -Xmx6g myprogram

于 2013-06-05T17:03:27.867 回答
1

java中的GC运行良好。如果你得到OutOfMemoryError你可能有内存泄漏(即你在你的集合中存储了太多)或者你没有为你的应用程序提供足够的堆。

我相信在您的情况下,您没有到达清除收集的代码。您可能在解析过程中失败。在这种情况下,首先尝试使用命令行选项向您的 java 进程添加更多内存-Xmx,例如-Xmx1024M(1GB)。

我相信您将能够找到帮助您成功完成解析的选项。

然后,如果您正在使用解析文件一次并终止的实用程序,那么您就完成了。但是,如果您的应用程序应该运行并解析越来越多的文件,请检查处理每个文件后内存使用量是否没有增加。如果它正在增长,请检查它是设计导致的还是由错误引起的。

如果是设计,请考虑重新设计。顺便说一句,您真的必须将所有行读入内存然后处理它们吗?你在做什么处理?您是否有机会逐行处理文件并显着减少内存使用量?

于 2013-06-05T17:08:51.277 回答
1

如果您用records列表中行的子字符串填充这些哈希图,您实际上是为每个子字符串完全存储这些行。

看看:Java 标准 API 中的内存泄漏陷阱

在这种情况下,答案是使用类似的东西:

String key = new String(record.substring(6,12));

或者

String key = record.substring(6,12).intern();
于 2013-06-05T17:16:53.417 回答
1

It may be that you have enough memory, but the memory is fragmented. How you build your ArrayList and HashMap is critical. E.g. are using StringBuilder?

Unless the entire code up to the error is shown, it is very hard to debug a memory problem remotely.

Also, it helps if we know the java version, environment, etc.

Also, do not forget that if you have a lot of objects with different sizes, the memory gets fragmented easier. And if the memory is barely enough to contain those objects, you can get memory errors.

Finally, you can initiate a garbage collection of your own ( - and most probably the JVM will know better :-) ).

于 2013-06-05T17:18:08.780 回答
0

Garbage Collector works only when you loose all references to Object. You say that some information is stored in HashMap, so Garbage Collector dont temove them.

于 2013-06-05T17:17:15.967 回答