Java Apache POI超出了GC开销限制
我有13个.xlsx文件,每个文件大约有1000行。现在我想用一张纸把它合并成一个.xlsx文件。我在这里使用代码 这是我的代码(改动很少,addSheet方法没有改变)Java Apache POI超出了GC开销限制,java,excel,garbage-collection,apache-poi,Java,Excel,Garbage Collection,Apache Poi,我有13个.xlsx文件,每个文件大约有1000行。现在我想用一张纸把它合并成一个.xlsx文件。我在这里使用代码 这是我的代码(改动很少,addSheet方法没有改变) 我能做什么?为什么会发生这种情况以及如何防止这种情况?发生此问题的原因如下 java.lang.OutOfMemoryError:GC开销限制超出错误是JVM表示应用程序花费太多时间进行垃圾收集而结果太少的一种方式。默认情况下,如果JVM花费超过总时间的98%进行GC,并且在GC之后仅恢复了不到2%的堆,则JVM将配置为抛出
我能做什么?为什么会发生这种情况以及如何防止这种情况?发生此问题的原因如下 java.lang.OutOfMemoryError:GC开销限制超出错误是JVM表示应用程序花费太多时间进行垃圾收集而结果太少的一种方式。默认情况下,如果JVM花费超过总时间的98%进行GC,并且在GC之后仅恢复了不到2%的堆,则JVM将配置为抛出此错误。 如果您只是想忽略此问题,可以设置以下vm选项:
-XX:-UseGCOverheadLimit
有关更多信息,请参阅
还可以使用以下开关为应用程序分配更多堆内存。在您的应用程序上运行一段时间的试验,并确定有多少内存适合您的应用程序
-Xms128m -Xmx512m(these switches sets the initial heap memory size to 128mb and Max memory to 512mb)
试着分配更多的内存
java -Xmx8192m
您还可以尝试一次合并一个xlsx文件,而不是一次加载所有xlsx文件
您还可以将此行移动到for循环中:
excellFile1.close();
因此,您可以立即关闭它。POI是出了名的内存不足,因此在处理大型Excel文件时,内存不足并不少见
当您能够加载所有原始文件并且只在编写合并文件时遇到问题时,您可以尝试使用
SXSSFWorkbook
而不是XSSFWorkbook
,并在添加一定量的内容后进行定期刷新(请参阅org.apache.poi.xssf.streaming
-package的poi文档)。通过这种方式,您不必将生成的整个文件保存在内存中,而只需保存一小部分。如果您可以避免使用方便但占用大量内存的工作簿API,请使用逐行处理数据的流逻辑,这将大大提高内存效率
尤其要特别注意以下各项的使用:
XSSFReader.SheetIterator,用于在图纸上循环
最后,请仔细看看API:XSSFSheetXMLHandler的用法。
用于使用图纸处理行
请参阅此项目的代码:
您可以通过创建自己的行来定义要如何处理每行:
新谢德勒
这非常类似于SAX解析,它不会占用您的ram一点时间
是否可以不更改虚拟机设置?如果没有,您能推荐一些其他库来处理这个问题而不超过GC限制吗?我想库不是问题,因为您在内存中保存了大量数据,我建议您查看源代码,通过源代码可以优化解决方案和/或使用-Xms-Xmx switches.Hm修改应用程序的堆大小分配。这两种选择都没有帮助我解决这个问题。该文件仅为2.9M。读取其他文件时没有任何问题。。。
java -Xmx8192m
excellFile1.close();
private void readSheet(StylesTable styles, ReadOnlySharedStringsTable sharedStringsTable,
InputStream sheetInputStream) throws IOException, ParserConfigurationException, SAXException {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
XMLReader sheetParser = saxFactory.newSAXParser().getXMLReader();
ContentHandler handler =
new XSSFSheetXMLHandler(styles, sharedStringsTable, sheetContentsHandler, true);
sheetParser.setContentHandler(handler);
sheetParser.parse(new InputSource(sheetInputStream));
}