Вопрос по java, itext, out-of-memory – Объединение 1000 PDF через iText создает ошибку java.lang.OutOfMemoryError: пространство кучи Java

4

Я пытаюсь объединить 1000 файлов PDF через iText. Я не уверен, где происходит утечка памяти. Ниже приведен пример кода. Обратите внимание, что я удаляю файл child-pdf, как только я сливаюсь с родительским файлом. Пожалуйста, укажите на ошибку в приведенном ниже коде или есть лучший способ сделать это без концепции памяти. Этот процесс выполняется через сервлет (не автономная программа)

FileInputStream local_fis = null;
BufferedInputStream local_bis = null;
File localFileObj = null;
for(int taIdx=0;taIdx

Ваш Ответ

7   ответов
2

что есть утечка памяти? Ваш объединенный документ должен полностью поместиться в память,Обойти это невозможно, и он может быть больше, чем размер кучи по умолчанию 64 МБ.в памяти (а не на диске).

Я неЯ не вижу проблемы с вашим кодом, но если вы хотите подробно его диагностировать,использовать visualvm 'профилировщик кучи (поставляется с JDK начиная с версии Java 6 10 или около того).

@micheal есть метод flush () на PdfWriter & PdfCopy который "Сбрасывает BufferedOutputStream ", Так что я неЯ думаю, что весь объединенный файл должен уместиться в памяти. Hari Gudigundla
Спасибо за ваше предложение Майкл. Я проверю профиль кучи и обновлю свои выводы Niger
Эй, Майкл, я пытался использовать visualvm, но не могу подключиться к удаленному. Начал новую тему для этогоstackoverflow.com/questions/1263991/... Niger
8

закрытие файла и удаление удалены для ясности):

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();
Отлично!! Здесь была утечка памяти. Недостающая строка была pdfWriter.freeReader (). Теперь не нужно увеличивать javaheap. Оно работает. Спасибо Niger
Я нашел еще одно решение без использования pdfwriter. for (int taIdx = 0; taIdx <totalSize; taIdx ++) {frObj = (Form3AReportObject) reportRows.get (taIdx); localfilename = companyId + "_" + frObj.empNumber + ".pdf»; PdfReader Reader = новый PdfReader (имя локального файла); document.setPageSize (reader.getPageSizeWithRotation (1)); PdfImportedPage pdfImportedPage = pdfCopy.getImportedPage (reader, 1); pdfCopy.addPage (pdfImportedPage); reader.close (); } Niger
1
И что заставляет вас говорить это? Откуда вы знаете, что ваши текущие настройки достаточно хороши? Вы проанализировали потребности памяти в этом коде и в приложении в целом? matt b
Это неНе имеет смысла - если текущие настройки были достаточно хорошими, то почему вы получаете OutOfMemoryErrors? Похоже, что вы добавляете больше объектов / данных в ваш документ pdfWriter и PDF с каждой итерацией. Это означает, что он увеличивается в размерах в PDF. matt b
Привет Мэтт, пожалуйста, проверьте комментарий ниже. Код выполняется без увеличения размера HEAP. Niger
Я думаю, что текущие настройки достаточно хороши и текущий код "должен" эффективно работать с этими настройками, так как я пишу страницу за страницей в поток (не сохраняя в памяти) Niger
-1

Вместо того, чтобы объединять 1000 PDF-файлов, попробуйте создать ZIP-архив из них.

0

Приведенный выше код пытается создатьPdfContentByte объект (cb) в цикле. Перемещение на улицу может решить проблему. Я использовал подобный код в своем приложении, чтобы без проблем соединить 13k отдельных PDF-файлов в один PDF-файл.

И где это? Косвенно? Если так, то где? Немного больше информации будет полезно Lonzak
0
public class PdfUtils {
     public static void concatFiles(File file1, File file2, File fileOutput) throws Exception {
          List islist =  new ArrayList();
          islist.add(file1);
          islist.add(file2);

          concatFiles(islist, fileOutput);
         }

         public static void concatFiles(List 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 
0

если вы неиспользовать InputStream? Если вы можете, попробуйте использовать только путь для вашего файла нановый PDFReader ("/ Somedirectory / файл «.).

Это заставит читателя действовать на диске.

Похожие вопросы