java.lang.OutOfMemoryError: GC overhead limit exceeded when loading an xlsx file

java.lang.OutOfMemoryError: GC overhead limit exceeded when loading an xlsx file

我明白这个错误是什么意思,我的程序消耗了太多内存,而且很长一段时间都没有恢复。

发生内存问题时,我的程序正在读取 6,2Mb xlsx 文件。

当我尝试监控程序时,它的内存消耗很快达到 1.2Gb,然后崩溃。读取6,2Mb文件时如何达到1,2Gb?

有没有办法分块打开文件?这样它就不必加载到内存中了?或者任何其他解决方案?

正是这部分导致了它。但既然它是一个图书馆,难道不应该以某种方式巧妙地处理它吗?它只有 200 000 行,只有 3 列。为了将来,我需要它与大约一起工作。 100 万条记录和更多列...

代码:

  Workbook myWorkBook;
        Sheet mySheet;
        if (filePath.contains(".xlsx")) {
            // Finds the workbook instance for XLSX file
             myWorkBook = new XSSFWorkbook(fis);
            // Return first sheet from the XLSX workbook
             mySheet = myWorkBook.getSheetAt(0);
             myWorkBook.close(); // Should I close myWorkBook before I get data from it?
        } 

如果您希望处理大型 XLSX 文件,则需要使用流式处理 XSSFReader class。由于数据为XML,可以使用StAX有效处理内容

这是(一种方法)如何从 xlsx 中获取 Inputstream

OPCPackage opc = OPCPackage.open(file);
XSSFReader xssfReader = new XSSFReader(opc);
SharedStringsTable sst = xssfReader.getSharedStringsTable();
XSSFReader.SheetIterator itr = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
while(itr.hasNext()) {
    InputStream sheetStream = itr.next();
    if(itr.getSheetName().equals(sheetName)) {  // Or you can keep track of sheet numbers
        in = sheetStream;
        return;
    } else {
        sheetStream.close();
    }
}

元素是 <row><c>(对于单元格)。您可以创建一个小的 xlsx 文件,将其解压缩并检查里面的 XML 以获得更多信息。

编辑: 有一些关于使用 SAX 处理数据的 examples,但使用 StAX 更好并且同样高效。