Mesclando 1000 PDF através iText lança java.lang.OutOfMemoryError: Espaço Java heap

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

  •  12-09-2019
  •  | 
  •  

Pergunta

Eu estou tentando mesclar arquivos PDF 1000 através iText. Eu não estou certo de onde o vazamento de memória está acontecendo. Abaixo está o código de exemplo. Note que eu estou removendo o arquivo filho-pdf assim que se fundem para o arquivo principal. Por favor pointout bug no código abaixo ou há alguma maneira melhor de fazer isso com a concepção de memória. Este processo é feito através de servlet (não autônomo programa)

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();
Foi útil?

Solução

Você pode querer tentar algo como o seguinte (a manipulação de exceção, fechar arquivo e apagar removido para maior clareza):

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

Outras dicas

Quem diz que há um vazamento de memória? Suas necessidades documento mesclado para caber na memória em sua totalidade, não há nenhuma maneira em torno dela, e pode muito bem ser maior do que o tamanho da pilha padrão de 64MB na memória (em vez de no disco).

Eu não vejo um problema com o seu código, mas se você quiser diagnosticá-la em detalhe, uso de VisualVM pilha profiler (vem com o JDK desde Java 6 update 10 ou assim).

E se você não usar InputStream? Se você puder, tente usar apenas o caminho para você arquivo em 'nova PdfReader ( '/ algumdiretorio / arquivo.').

Isto faz o leitor a agir no disco.

O código acima está tentando criar um objeto PdfContentByte (cb) dentro do loop. Movê-lo fora pode corrigir o problema. I utilizado código semelhante no meu aplicativo para unir 13k PDFs individuais em que um PDF sem problemas.

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

Em vez de juntar 1000 PDFs, tente criar um zip deles.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top