1

I need to open, alter and write an excel file. As the altering process is a bit more complex I'll leave it out, as the issue does not lie within it. The issue I am running into is while writing the file to disk. The issue starts with files at around 7MB size (doesn't matter if its formula or values).

I prepared following MVCE:

public static void main(String[] args) throws EncryptedDocumentException, IOException, InvalidFormatException {
    String filePath = "C:\\temp";
    String outputFilePath = "C:\\temp\\test";
    ZipSecureFile.setMinInflateRatio(0);
    File f = new File(filePath, "Test.xlsx");
    try (XSSFWorkbook workBook = new XSSFWorkbook(f)) {
        System.out.println("writing file");
        File outputFile = new File(outputFilePath, f.getName());
        try (FileOutputStream fos = new FileOutputStream(outputFile)) {
            workBook.write(fos);
        }
        workBook.close();
    }
    System.out.println("fin");
}

This code already causes the issue I am running into. The exact stacktrace is:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.toByteArray(ByteArrayOutputStream.java:191)
    at org.apache.poi.openxml4j.opc.internal.MemoryPackagePartOutputStream.flush(MemoryPackagePartOutputStream.java:76)
    at org.apache.poi.openxml4j.opc.internal.MemoryPackagePartOutputStream.close(MemoryPackagePartOutputStream.java:51)
    at org.apache.poi.xssf.usermodel.XSSFSheet.commit(XSSFSheet.java:3575)
    at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:462)
    at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:467)
    at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:236)
    at test.TestWriteOriginalWorkbook.main(TestWriteOriginalWorkbook.java:25)

Though the trace itself varies from file to file, the exception itself stays the same all the time.

As far as I know, the only way to solves this, would be to increase the available memory for the application. Though if possible, I would like to avoid that. I just checked for my MaxHeapSize which defaults to around 260MB which seems quite low. So an increase to 1GB would be acceptable if necessary.

I ran this code with -Xmx1g and get the same exception with a different cause:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3045)
    at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3065)
    at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3198)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3414)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1272)
    at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1259)
    at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
    at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:227)
    at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:219)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.parseSheet(XSSFWorkbook.java:452)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:417)
    at org.apache.poi.ooxml.POIXMLDocument.load(POIXMLDocument.java:184)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:286)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:323)
    at test.TestWriteOriginalWorkbook.main(TestWriteOriginalWorkbook.java:21)
Cleaning up unclosed ZipFile for archive C:\temp\Test.xlsx

To summarize the question: What can I do to improve the performance of workBook.write(fos); to handle files above 7MB size (preferably up to 15MB)?


Test.xlsx is an excel file with values only. I created it with 1 in the whole first column as well as the second column until row 443269.

XtremeBaumer
  • 6,275
  • 3
  • 19
  • 65
  • If even POI’s SXSSF API can’t serve you, the only solution is to look for the [alternatives to using Apache POI](https://stackoverflow.com/q/4601722/2711488)… – Holger Sep 12 '19 at 10:33
  • 1
    For creating a `XSSFWorkbook` is is necessary to read all the different content of the `*.xlsx` `ZIP` archive into objects in memory. `Apache poi` does this using at least two different kinds of object per `Excel` object. There are the low level `CT*` objects of `ooxml-schemas` which bases on `XML` read from the files, which `apache poi` then puts in it's high level `XSSF*` objects. This is not really memory saving. But the other approach would be only using the low level `CT*` objects or manupulating the `XML` directly, which is not really easy to program. – Axel Richter Sep 12 '19 at 11:04

0 Answers0