java.lang.OutOfMemoryError:读取txt文件并写入xlsx文件时的java堆空间

java.lang.OutOfMemoryError:读取txt文件并写入xlsx文件时的java堆空间,java,memory,Java,Memory,我编程是为了创建一个工具,将编码的.txt文件翻译成可读的.xlsx文件。(我需要使用xlsx,因为我使用的列数超过256列,所以我在写行和列时使用XSSFWorkbook) 编码部分正常。。我知道这一点,因为我已经验证了好几次,但当我尝试在代码中添加新的编码映射时,所有结果都是: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Unknow

我编程是为了创建一个工具,将编码的.txt文件翻译成可读的.xlsx文件。(我需要使用xlsx,因为我使用的列数超过256列,所以我在写行和列时使用XSSFWorkbook)

编码部分正常。。我知道这一点,因为我已经验证了好几次,但当我尝试在代码中添加新的编码映射时,所有结果都是:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.io.ByteArrayOutputStream.write(Unknown Source)
    at org.apache.poi.openxml4j.opc.internal.MemoryPackagePartOutputStream.write(MemoryPackagePart OutputStream.java:88)
at org.apache.xmlbeans.impl.store.Cursor._save(Cursor.java:590)
at org.apache.xmlbeans.impl.store.Cursor.save(Cursor.java:2544)
at org.apache.xmlbeans.impl.values.XmlObjectBase.save(XmlObjectBase.java:212)
at org.apache.poi.xssf.usermodel.XSSFSheet.write(XSSFSheet.java:2480)
at org.apache.poi.xssf.usermodel.XSSFSheet.commit(XSSFSheet.java:2439)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:196)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:200)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:204)
at model.Conversione.traduzioneFile(Conversione.java:241)
at model.Main.scriviFile(Main.java:76)
at model.Main.main(Main.java:52)
错误发生在3000/4000行之后,内存是这样运行的 起始值:

14443720 **:13572128 **:12078128 **:10575592 **:14126224->新增加值始终低于起始值,然后降低 **:12559920 **:11811440 **:10229128 **:13751400->。。。 **:13011080

“编码映射”通常是
HashMap
类型的映射。 (我这样做是因为我不能使用数据库.)

所以程序主要是:

-首先实例化并创建整个地图, -从.txt文件中读取行, -拆分行,获取一个标记,使用地图将其转换为行和列 -wb.write(文件输出流) -结束

即使在翻译操作中没有考虑到我添加的地图,我也无法理解为什么会发生此错误

为什么内存量如此多变?(但永远不要回到起始值?)

如果我在某些方面不清楚,请询问。。我不知道该怎么办

起初,我认为这是一个.xlsx文件越来越大的缓冲问题(即使..如我所说..没有任何变化,因为没有使用新的映射)

如有任何提示,我们将不胜感激


Lucia

您可以使用jvisualvm或jmap-histo:live检查占用内存的内容。如果应用程序确实需要内存,您可以尝试增加内存限制-Xmx…

默认情况下,Eclipse将分配多达384 MB的Java堆内存。对于所有典型的开发任务来说,这应该足够了。但是,根据您正在运行的JRE、您正在使用的其他插件的数量以及您将使用的文件的数量,您可能需要增加这个数量。Eclipse允许您使用-vmargs命令行参数直接将参数传递给Java VM,该参数必须在所有其他Eclipse特定参数之后。因此,为了增加可用堆内存,您通常会使用:

eclipse -vmargs -Xmx<memory size>
eclipse-vmargs-Xmx
将该值设置为大于“384M”(384MB——默认值)

使用Oracle(Sun)VM时,可能还需要增加永久性生成内存的大小。默认最大值为64 MB,但根据插件配置和使用情况,可能需要更多。当VM耗尽永久生成内存时,它可能会在类加载期间崩溃或挂起。使用Sun JRE版本1.5.0_07或更高版本时,此故障不太常见。使用-XX:MaxPermSize=参数增加最大永久生成大小:

**eclipse -vmargs -XX:MaxPermSize=<memory size>**
**eclipse-vmargs-XX:MaxPermSize=**

这与缓冲无关。内存不足是因为堆中的对象太多和/或最大内存的
-Xmx
设置太低。您可以在Eclipse中与测试/实用程序对应的参数选项卡中的“运行配置”中增加
-Xmx
。在VM参数块中添加
-Xmx 512M
(大约)


但真正的问题是,您试图同时在内存中存储太多的对象。我不确定我是否理解你的
HashMap
HashMap
。如果文本文件中每行都有一个
HashMap
,那么这将占用大量内存@AKJ的回答提供了一些工具来诊断哪些物体占用了最多的空间。是一个很好的起点。

如果您在运行独立java应用程序时在eclipse中遇到这个问题。右键单击java程序,然后单击“运行方式->运行配置”。单击参数选项卡,并在VM参数字段中键入-Xms1024M-Xmx1024M。这会在从eclispe运行时增加VM大小。

我建议您使用SXSSFWorkbook(需要Apache POI>=3.8 beta 3)而不是建议使用的XSSFWorkbook

创建一个行访问窗口大小为20的工作簿,即内存中最多只保留20行,其余的刷新到磁盘上


执行此操作时需要注意一些陷阱,如果需要调用SXSSFSheet.autoSizeColumn(int),请避免将空值放入单元格中,并尽快调用SXSSFSheet.TrackAllColumnsFrautosizing()(需要Apache POI>=3.15)稍后,我将自动计算列的大小。

我想我无法增加内存,因为我仍然需要添加大量映射,所以我会得出相同的结论。。现在我正试图理解如何使用jvisualvm。多谢了,这与eclipse的记忆无关。这与eclipse在运行其测试和程序时添加的VM设置有关。您可以从运行配置菜单和参数选项卡中获得。
final SXSSFWorkbook workbook = new SXSSFWorkbook(20);