Apache POI超出了GC开销限制

Mar*_*ess 8 java excel garbage-collection apache-poi

我有13个.xlsx文件,每个文件大约有1000行.现在我想用一张表将它合并到一个.xlsx文件中.我正在使用此处的代码 http://blog.sodhanalibrary.com/2014/11/merge-excel-files-using-java.html#.Vi9ns36rSUk.

这是我的代码(几个更改,addSheet方法不变)

try {
        FileInputStream excellFile1 = new FileInputStream(new File("tmp_testOut1000.xlsx"));
        XSSFWorkbook workbook1 = new XSSFWorkbook(excellFile1);
        XSSFSheet sheet1 = workbook1.getSheetAt(0);

        for(int i = 2; i < 14; i++){
            FileInputStream excellFile2 = new FileInputStream(new File("tmp_testOut" + i + "000.xlsx"));
            XSSFWorkbook workbook2 = new XSSFWorkbook(excellFile2);
            XSSFSheet sheet2 = workbook2.getSheetAt(0);
            System.out.println("add " + i);
            addSheet(sheet1, sheet2);
        }

        excellFile1.close();

        // save merged file
        System.out.println("merging");
        File mergedFile = new File("merged.xlsx");
        if (!mergedFile.exists()) {
            mergedFile.createNewFile();
        }
        FileOutputStream out = new FileOutputStream(mergedFile);
        System.out.println("write");
        workbook1.write(out);
        out.close();
        System.out.println("Files were merged succussfully");
    } catch (Exception e) {
        e.printStackTrace();
    }
Run Code Online (Sandbox Code Playgroud)

所有文件都在加载和合并但是在"写入"sysout后我得到了

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.apache.xmlbeans.impl.store.Xobj.new_cursor(Xobj.java:1829)
at org.apache.xmlbeans.impl.values.XmlObjectBase.newCursor(XmlObjectBase.java:293)
at org.apache.xmlbeans.impl.values.XmlComplexContentImpl.arraySetterHelper(XmlComplexContentImpl.java:1151)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTFontsImpl.setFontArray(Unknown Source)
at org.apache.poi.xssf.model.StylesTable.writeTo(StylesTable.java:424)
at org.apache.poi.xssf.model.StylesTable.commit(StylesTable.java:496)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:341)
at org.apache.poi.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:345)
at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:206)
at Start.main(Start.java:275)
Run Code Online (Sandbox Code Playgroud)

我能做什么?为什么会发生这种情况以及如何预防?

pie*_*t.t 15

众所周知,POI需要占用大量内存,因此在处理大型Excel文件时,内存耗尽并不少见.

当您能够加载所有原始文件并且只在编写合并文件时遇到问题,您可以尝试使用SXSSFWorkbook而不是XSSFWorkbook在添加一定量的内容后进行常规刷新(请参阅-package的poi-documentation org.apache.poi.xssf.streaming).这样,您不必将整个生成的文件保留在内存中,而只需保留一小部分.


Viv*_*ngh 2

出现此问题的原因如下

\n\n

java.lang.OutOfMemoryError:超过 GC 开销限制错误是 JVM\xe2\x80\x99s 发出信号的方式,表明您的应用程序花费了太多时间进行垃圾收集,但结果却太少。默认情况下,如果 JVM 花费超过总时间的 98% 来执行 GC,并且在 GC 后仅恢复了不到 2% 的堆,则 JVM 配置为引发此错误。\n

\n\n

如果你只是想忽略这个问题,你可以设置以下虚拟机选项:

\n\n
-XX:-UseGCOverheadLimit\n
Run Code Online (Sandbox Code Playgroud)\n\n

有关详细信息,请参阅有关 GC 开销的链接。

\n\n

您还可以使用以下开关为您的应用程序分配更多堆内存。在您的应用程序上运行一段时间的试点,并确定多少内存更适合您的应用程序

\n\n
-Xms128m -Xmx512m(these switches sets the initial heap memory size to 128mb and Max memory to 512mb)\n
Run Code Online (Sandbox Code Playgroud)\n