通过iText合并1000 PDF会抛出java.lang.OutOfMemoryError:java堆空间

通过iText合并1000 PDF会抛出java.lang.OutOfMemoryError:java堆空间,java,itext,out-of-memory,Java,Itext,Out Of Memory,我正试图通过iText合并1000个PDF文件。我不确定内存泄漏发生在哪里。下面是示例代码。请注意,我将在合并到父文件后立即删除子pdf文件。请指出下面代码中的错误,或者有没有更好的方法在没有内存的情况下实现这一点。此过程通过servlet完成(不是独立程序) FileInputStream local\u fis=null; BufferedInputStream local_bis=null; 文件localFileObj=null; 对于(int-taIdx=0;taIdx您是否尝试过从默

我正试图通过iText合并1000个PDF文件。我不确定内存泄漏发生在哪里。下面是示例代码。请注意,我将在合并到父文件后立即删除子pdf文件。请指出下面代码中的错误,或者有没有更好的方法在没有内存的情况下实现这一点。此过程通过servlet完成(不是独立程序)

FileInputStream local\u fis=null;
BufferedInputStream local_bis=null;
文件localFileObj=null;

对于(int-taIdx=0;taIdx您是否尝试过从默认值(仅64mb)增加最大堆大小

见:


谁说内存泄漏了?合并的文档需要完整地放入内存中,没有办法绕过它,而且它很可能会大于内存(而不是磁盘)中的默认堆大小64MB


我看不出您的代码有问题,但如果您想详细诊断它(自Java 6 update 10以来随JDK提供)。

您可能想尝试以下操作(为了清晰起见,请执行异常处理、关闭文件和删除操作):

for(int-taIdx=0;taIdx
不要合并1000个PDF,而是尝试创建它们的zip文件。

如果不使用InputStream怎么办?如果可以,请尝试仅使用“new PDFReader”(/somedirectory/file.”上的文件路径


这使得读卡器可以在磁盘上执行操作。

上面的代码试图在循环中创建一个
PdfContentByte
对象(
cb
)。将其移到外部可能会解决此问题。我在应用程序中使用类似的代码将13k个单独的PDF无缝地缝合到一个PDF中。

公共类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");        
          }               
         }
   }
公共静态void concatFiles(文件file1、文件file2、文件fileOutput)引发异常{ List islist=new ArrayList(); islist.add(文件1); islist.add(文件2); concatFiles(islist、fileOutput); } 公共静态void concatFiles(列表文件列表、文件文件输出)引发异常{ 如果(filelist.size()>0){ PdfReader reader=newpdfreader(newfileinputstream(filelist.get(0)); Document Document=新文档(reader.getPageSizeWithRotation(1)); PdfCopy cp=新的PdfCopy(文档,新文件输出流(文件输出)); document.open(); 用于(文件:文件列表){ PdfReader r=新PdfReader(新文件输入流(文件));
对于(int k=1;k增加堆大小不会有帮助。因为这个过程将在Servlet环境中运行,并且可能会出现多个请求。所以我们需要找出内存泄漏。是什么让你这么说的?你怎么知道你当前的设置足够好?你分析过这段代码和整个应用程序的内存需求吗?我是墨迹的当前设置是足够好的,当前的代码“必须”与此设置有效地工作,因为我正在写一页一页到流(不存储在内存中)这没有多大意义-如果当前设置足够好,那么为什么要避免内存错误?看起来每次迭代都会在pdfWriter和PDF文档中添加更多对象/数据。这意味着每个PDF的大小都在增长。与其假设解决方案不起作用,不如尝试一下,然后确定答案吗?关于从默认值增加最大堆大小的问题是第一个疑难解答步骤。当您遇到堆大小问题时,任何检查表上的第一步都必须是“您是否更改了默认设置?”谢谢你的建议Micheal。我将检查堆探查器并更新我的查找Shey Micheal我尝试使用visualvm但无法连接到远程。为此@Micheal启动了一个新线程PdfWriter和PdfCopy上有flush()方法,该方法“刷新BufferedOutputStream”。因此,我认为不需要将整个合并文件放入内存中。太好了!!内存泄漏就在这里。缺少的行是pdfWriter.freerereader()。现在不需要增加javaheap。它可以工作了。感谢我在不使用pdfWriter的情况下又找到了一个解决方案。对于(int taIdx=0;taIdx这是哪里?隐式的?如果是哪里?多了解一些信息会很有帮助
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();
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");        
          }               
         }
   }