Bo Öberg
Bo Öberg

Reputation: 31

Using iText: java.lang.OutOfMemoryError: Requested array size exceeds VM limit

I'vew been using iText 4.2.1 and java 1.6 to generate PDF-files. My task is to add two fields having some random content using a template pdf. It works fine even with an 1GB large PDF. But now the environment demands java 7 and I run into this Out of memory-problem. I'v upgraded the iText to 5.5.3, but still the same issue. The code is trivial:

public final class PdfHelper
{
    public static void randomizePDFStream(InputStream in, OutputStream out)
    {
        try
        {
            PdfReader ReadInputPDF;
            ReadInputPDF = new PdfReader(in);
-> crash            PdfStamper stamper = new PdfStamper(ReadInputPDF, out);
            HashMap<String, String> hMap = ReadInputPDF.getInfo();
            hMap.put("Title", "RANDOM PDF TITLE: " + System.nanoTime() + ", " + System.currentTimeMillis());
            hMap.put("Subject", "RANDOM PDF SUBJECT: " + System.currentTimeMillis() + ", " + System.nanoTime());
            stamper.setMoreInfo(hMap);
            stamper.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

This gives the following stack dump when using a 1GB large pdf file :

Caught: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
        at java_util_concurrent_Future$get.call(Unknown Source)
        at Main.awaitCompletion(Main.groovy:222)
        at Main$awaitCompletion.callCurrent(Unknown Source)
        at Main.run(Main.groovy:113)
Caused by: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
        at com.itextpdf.text.io.StreamUtil.inputStreamToArray(StreamUtil.java:74)
        at com.itextpdf.text.io.RandomAccessSourceFactory.createSource(RandomAccessSourceFactory.java:146)
        at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:351)
        at com.itextpdf.text.pdf.PdfReader.<init>(PdfReader.java:371)
        at PdfHelper.randomizePDFStream(PdfHelper.java:65)

This is called from a groovy script with this basic code:

mPDFFiles[i] = new java.io.File(getTempDirectory(), String.format("temp_file_%s_%s.pdf", System.nanoTime(), i));
mPDFFiles[i].createNewFile();

input = new BufferedInputStream(new FileInputStream(mTemplateFiles[i]));
output = new BufferedOutputStream(new FileOutputStream(mPDFFiles[i]));

long start=System.currentTimeMillis();
PdfHelper.randomizePDFStream(input, output);
output.flush();
println "Conversion time: " + (System.currentTimeMillis()-start) + " ms."

Anyone having an idea how to get this to work?

Upvotes: 3

Views: 10748

Answers (3)

Johannes
Johannes

Reputation: 162

Some options of what you could do:

  1. Tell the JVM (which executes your Groovy code and the PdfStamper inside) to allow use of more memory (-Xmx etc. Consult your JVM documentation).
  2. Find an implementation that does not require to load the complete PDF into memory (at least not at once).

(I'm wondering why the implementation of iText and its PdfStamper is not efficient enough to accomplish your task without using a huge amount of memory...)

Upvotes: 0

Lonzak
Lonzak

Reputation: 9816

The error says "Requested array size exceeds VM limit" - the maximum size of an array is around 2GB (Integer.MAX_VALUE). The question is what VM are you running? 32 GB or 64 GB? You may try the following options (64 Bit VM):

-XX:+UseCompressedOops

Upvotes: 0

Nirav Prajapati
Nirav Prajapati

Reputation: 3005

You can use command-line parameters to increase the amount of memory available to Java. Here is an example of the command-line parameters that I use - you should change the numbers as appropriate for your needs and system memory capacity:

Xms256m -Xmx1024m -XX:+DisableExplicitGC -Dcom.sun.management.jmxremote
-XX:PermSize=256m -XX:MaxPermSize=512m

Upvotes: 1

Related Questions