2014-10-08 140 views
2

我已經使用iText 4.2.1和Java 1.6生成PDF文件。我的任務是使用模板pdf添加兩個有一些隨機內容的字段。即使使用1GB大型PDF,它也能正常工作。但是現在環境需要java 7,我遇到了這個內存不足的問題。 我已將iText升級到5.5.3,但仍是同樣的問題。 代碼很簡單:使用iText:java.lang.OutOfMemoryError:請求的數組大小超過VM限制

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(); 
     } 
    } 
} 

採用1GB超大的PDF文件時,這提供了以下堆棧轉儲:

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) 

這是從Groovy腳本調用這個基本代碼:

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." 

任何人有一個想法如何讓這個工作?

+0

你嘗試增加JVM堆的大小? http://viralpatel.net/blogs/jvm-java-increase-heap-size-setting-heap-size-jvm-heap/ – Leo 2014-10-08 11:47:22

+0

嗯,當然我已經嘗試過增加Xmx和MaxHeapSize,但仍然是同樣的問題。我現在正在運行-Xms = 8192m -Xmx16g -XX:MaxPermSize = 8192m。正如我所提到的,使用jdk1.6一切運行良好。 – 2014-10-09 04:59:15

+0

'PdfStamper stamper = new PdfStamper(ReadInputPDF,out,true);'在追加模式下。但我懷疑。似乎有一個特定的數據錯誤。嘗試另一種PDF,將PDF寫入臨時文件,然後使用該新的臨時PDF。 – 2014-10-09 08:56:22

回答

1

您可以使用命令行參數來增加可用於Java的內存量。下面是我使用的命令行參數的一個例子 - 你應該改變數以適合您的需求和系統內存容量:

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

的你可以做什麼的一些選項:

  1. 告訴JVM(它執行你的Groovy代碼和PdfStamper內部)以允許使用更多的內存(-Xmx等等。請參閱你的JVM文檔)。
  2. 查找不需要將完整PDF加載到內存中的實現(至少不是一次)。

(我不知道爲什麼iText的實施及其PdfStamper不足以有效地完成任務,而無需使用大量的內存...)

1

錯誤說「請求數組的大小超過VM限制「 - 數組的最大大小約爲2GB(Integer.MAX_VALUE)。問題是你在運行什麼虛擬機? 32 GB或64 GB?你可以試試下面的選項(64位VM):

-XX:+ UseCompressedOops

相關問題