javaitextflying-saucerxhtmlrenderer

flying saucer (xhtmlrenderer) out of memory


I'm trying to use flying saucer to create a very large PDF and it seems to be running out of memory.

below are a couple of stack traces which suggest to me that flying saucer is not completely scalable... or am i doing something wrong?

java.lang.OutOfMemoryError: Java heap space
        at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(XMLStringBuffer.java:205)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.refresh(XMLDocumentScannerImpl.java:1520)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.invokeListeners(XMLEntityScanner.java:2070)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanLiteral(XMLEntityScanner.java:1063)
        at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanAttributeValue(XMLScanner.java:974)
        at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanAttribute(XMLNSDocumentScannerImpl.java:460)
        at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:277)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2747)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:637)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:708)
        at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313)
        at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.createXMLResource(XMLResource.java:189)
        at org.xhtmlrenderer.resource.XMLResource.load(XMLResource.java:71)

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2882)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:597)
    at java.lang.StringBuffer.append(StringBuffer.java:329)
    at org.xhtmlrenderer.css.newmatch.Matcher$Mapper.mapChild(Matcher.java:385)
    at org.xhtmlrenderer.css.newmatch.Matcher.matchElement(Matcher.java:153)
    at org.xhtmlrenderer.css.newmatch.Matcher.getMapper(Matcher.java:235)
    at org.xhtmlrenderer.css.newmatch.Matcher.getCascadedStyle(Matcher.java:85)
    at org.xhtmlrenderer.context.StyleReference.getCascadedStyle(StyleReference.java:199)
    at org.xhtmlrenderer.layout.SharedContext.getStyle(SharedContext.java:548)
    at org.xhtmlrenderer.layout.SharedContext.getStyle(SharedContext.java:527)
    at org.xhtmlrenderer.layout.BoxBuilder.createChildren(BoxBuilder.java:1069)
    at org.xhtmlrenderer.layout.BoxBuilder.createChildren(BoxBuilder.java:113)
    at org.xhtmlrenderer.render.BlockBox.ensureChildren(BlockBox.java:902)
    at org.xhtmlrenderer.layout.BoxBuilder.createChildren(BoxBuilder.java:1115)
    at org.xhtmlrenderer.layout.BoxBuilder.createChildren(BoxBuilder.java:113)
    at org.xhtmlrenderer.render.BlockBox.ensureChildren(BlockBox.java:902)
    at org.xhtmlrenderer.layout.BoxBuilder.createChildren(BoxBuilder.java:1135)

Solution

  • You probably just need to increase the heap size; e.g. try adding -Xmx256m to the java command that is used to launch the application.

    You are probably also right in your inference that flying saucer is not totally scalable. I expect that it creates and uses in-memory representations of the complete input XML and the complete target PDF file. (It would most likely be easiest to do it that way.)

    However "a very large" PDF file is not scalable either as it is likely to cause problems for people downloading and viewing it. So maybe you should look at generating multiple PDF files.