繁体   English   中英

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

[英]java.lang.OutOfMemoryError: Java heap space when reading from a txt file and writing to an xlsx file

我正在编程,以便创建一个工具来将编码的.txt文件转换为可读的.x​​lsx文件。 (我需要使用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<Integer,Hashmap<Integer,String>>映射。 (我这样做是因为不能使用数据库。)

所以程序主要是:

- 首先实例化并创建整个地图,从.txt文件中读取 - 读取行, - 拆分行,获取令牌,使用地图转换它并将其放入行和列-wb.write(fileOutputStream fos)-fos。关。

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

为什么内存数量如此可变? (但永远不会回到起点?)

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

一开始我以为.xlsx文件的大小增加是一个缓冲问题(即使..如我所说..没有任何变化,因为未使用新的映射)。

任何提示表示赞赏。

圣卢西亚

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

我建议你使用SXSSFWorkbook(需要Apache POI> = 3.8 beta 3)而不是XSSFWorkbook,因为它在这里建议。

final SXSSFWorkbook workbook = new SXSSFWorkbook(20);

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

这样做时需要注意一些陷阱,如果以后需要调用SXSSFSheet.autoSizeColumn(int),请避免将空值放入单元格中,并尽快调用SXSSFSheet.trackAllColumnsForAutoSizing()(需要Apache POI> = 3.15)。自动计算列的大小。

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

缺省情况下,Eclipse将分配最多384 MB的Java堆内存。 这应该适用于所有典型的开发任务。 但是,根据您运行的JRE,您正在使用的其他插件的数量以及您将使用的文件数量,您可以想象必须增加此数量。 Eclipse允许您使用-vmargs命令行参数将参数直接传递给Java VM,该参数必须跟随所有其他Eclipse特定参数。 因此,为了增加可用的堆内存,通常可以使用:

eclipse -vmargs -Xmx<memory size>

将值设置为大于“384M”(384兆字节 - 默认值)。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM