iText を介して 1000 PDF をマージすると、java.lang.OutOfMemoryError がスローされます。Java ヒープ領域

StackOverflow https://stackoverflow.com/questions/1260895

  •  12-09-2019
  •  | 
  •  

質問

iText を介して 1000 個の PDF ファイルを結合しようとしています。どこでメモリリークが発生しているのかわかりません。以下はサンプルコードです。親ファイルにマージしたらすぐに子 PDF ファイルを削除していることに注意してください。以下のコードのバグを指摘してください。あるいは、メモリの概念を使用せずにこれを行うより良い方法はありますか。このプロセスはサーブレットを通じて実行されます (スタンドアロン プログラムではありません)。

FileInputStream local_fis = null;
BufferedInputStream local_bis = null;
File localFileObj = null;
for(int taIdx=0;taIdx<totalSize;taIdx++){
    frObj = (Form3AReportObject)reportRows.get(taIdx);
    localfilename = companyId + "_" +  frObj.empNumber + ".pdf";

    local_fis = new FileInputStream(localfilename);
    local_bis = new BufferedInputStream(local_fis); 
    pdfReader = new PdfReader(local_bis);

    cb = pdfWriter.getDirectContent(); 
    document.newPage();
    page = pdfWriter.getImportedPage(pdfReader, 1);
    cb.addTemplate(page, 0, 0);
    local_bis.close();
    local_fis.close();

    localFileObj = new File(localfilename);
    localFileObj.delete();
}
document.close();
役に立ちましたか?

解決

次のようなことを試してみるとよいでしょう (わかりやすくするために、例外処理、ファイルのクローズと削除を削除しました)。

for(int taIdx = 0; taIdx < totalSize; taIdx++) {
    Form3AReportObject frObj = (Form3AReportObject)reportRows.get(taIdx);

    localfilename = companyId + "_" +  frObj.empNumber + ".pdf";

    FileInputStream local_fis = new FileInputStream(localfilename);

    pdfWriter.freeReader(new PdfReader(local_fis));

    pdfWriter.flush();
}

pdfWriter.close();

他のヒント

メモリリークがあると誰が言ったでしょうか?マージされたドキュメントは全体がメモリに収まる必要がありますが、これを回避する方法はなく、デフォルトのヒープ サイズである 64 MB よりも大きくなる可能性があります。 記憶の中で (ディスク上ではなく)。

コードに問題はありませんが、詳細に診断したい場合は、 VisualVM のヒープ プロファイラーを使用する (Java 6 Update 10 以降には JDK が付属しています)。

InputStream を使用しない場合はどうなるでしょうか?可能であれば、「new PDFReader("/somedirectory/file.") 上のファイルのパスだけを使用してみてください。

これにより、リーダーがディスク上で動作するようになります。

上記のコードは、 PdfContentByte 物体 (cb) ループ内で。屋外に移動すると問題が解決する可能性があります。私はアプリケーションで同様のコードを使用して、13,000 個の個別の PDF を問題なく 1 つの PDF に結合しました。

public class PdfUtils {
     public static void concatFiles(File file1, File file2, File fileOutput) throws Exception {
          List<File> islist =  new ArrayList<File>();
          islist.add(file1);
          islist.add(file2);

          concatFiles(islist, fileOutput);
         }

         public static void concatFiles(List<File> filelist, File fileOutput) throws Exception {
          if (filelist.size() > 0) {
                 PdfReader reader = new PdfReader(new FileInputStream( filelist.get(0)) );
                 Document document = new Document(reader.getPageSizeWithRotation(1));

           PdfCopy cp = new PdfCopy(document,  new FileOutputStream( fileOutput ));

           document.open();


           for (File file : filelist ) {

                PdfReader r = new PdfReader( new FileInputStream( file));
                for (int k = 1; k <= r.getNumberOfPages(); ++k) {
                    cp.addPage(cp.getImportedPage(r, k));
                }
                cp.freeReader(r);

           }
           cp.close();
           document.close();
          } else{             
           throw new Exception("La lista dei pdf da concatenare è vuota");        
          }               
         }
   }

1,000 個の PDF を結合する代わりに、それらの PDF を作成してみてください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top