Memory management 在打印和合并pdf文件时,将iText与Java结合使用以避免内存泄漏和不必要的内存消耗的最佳做法是什么

Memory management 在打印和合并pdf文件时,将iText与Java结合使用以避免内存泄漏和不必要的内存消耗的最佳做法是什么,memory-management,out-of-memory,itext,heap-memory,Memory Management,Out Of Memory,Itext,Heap Memory,我正在使用iText 2.1.7库创建pdf报告。所有页面中只有两个小日志作为图像内容。Rest是所有文本和表格内容。我将图像设置为单例,以避免图像使用额外的内存。这似乎可以很好地处理多达10000条记录。但除此之外,堆正在耗尽空间。当前堆大小设置为1Gb 在执行pdf生成时,是否有其他优化可以减少内存消耗 更新1:添加更多详细信息和代码 我的要求是为每个记录打印单独的pdf文件,并将它们合并到一个pdf文件中作为最终输出。为了减少内存使用,我正在批量加载数据,并在加载下一批数据之前执行“打印+

我正在使用iText 2.1.7库创建pdf报告。所有页面中只有两个小日志作为图像内容。Rest是所有文本和表格内容。我将图像设置为单例,以避免图像使用额外的内存。这似乎可以很好地处理多达10000条记录。但除此之外,堆正在耗尽空间。当前堆大小设置为1Gb

在执行pdf生成时,是否有其他优化可以减少内存消耗

更新1:添加更多详细信息和代码

我的要求是为每个记录打印单独的pdf文件,并将它们合并到一个pdf文件中作为最终输出。为了减少内存使用,我正在批量加载数据,并在加载下一批数据之前执行“打印+合并”。我使用的方法如下所示:

    // This method is used to print seperate pdf files for each record to be printed. Each record prints a seperate pdf file with 1 to 4 pages containing tabular data.
        public byte[] print(PrintData printData) throws Exception
        {
                ByetArrayOutputStream outputStream = new ByetArrayOutputStream();
                // create a document
                Document document = new Document()
                // create the writer
                pdfWriter = PdfWriter.getInstance(document, outputStream);
                // open the document
                document.open();
                // build the page
                addPdfContents(document, printData);
                // close the document
                document.close();
                pdfWriter.close();
                byte[] printFile = outputStream.toByteArray();
                outputStream.close();
                return printFile;
         }

//the final document and output stream are defined outside as class variables. which will be closed after the final merge operation.

   PdfCopy copier = null;
   ByteArrayOutputStream outputStream = null;

   public void initializeFinalDoc(){
        outputStream = new ByteArrayOutputStream();
        Ddocument document = new Document();
        copier = new PdfCopy(document, outputStream);
        document.open();
   }

    public byte[] getFinalDoc(){
        document.close();
        outputStream.close();
        return outputStream.toByteArray();
    }
// After printing individual files it is merged with the master document to get the final output as a single merged document.
    public void merge(byte[] eachFile) throws Exception
    { 
            if(eachFile != null)
            {
                PdfReader reader = new PdfReader(eachFile);
                PdfImportedPage page;
                int numberOfPages = reader.getNumberOfPages();
                for(int i = 0; i < numberOfPages;)
                {
                    ++i;
                    page = pdfCopier.getImportedPage(reader, i);
                    pdfCopier.addPage(page);
                }
                pdfCopier.freeReader(reader);
            }
        }
//此方法用于为每个要打印的记录打印单独的pdf文件。每个记录打印一个单独的pdf文件,包含1到4页的表格数据。
公共字节[]打印(PrintData PrintData)引发异常
{
byetarayoutputstream outputStream=新的byetarayoutputstream();
//创建文档
文档=新文档()
//创造作家
pdfWriter=pdfWriter.getInstance(文档,outputStream);
//打开文档
document.open();
//构建页面
添加PDF内容(文档、打印数据);
//关闭文档
document.close();
pdfWriter.close();
byte[]printFile=outputStream.toByteArray();
outputStream.close();
返回打印文件;
}
//最终文档和输出流在外部定义为类变量。将在最终合并操作后关闭。
PdfCopy复印机=空;
ByteArrayOutputStream outputStream=null;
public void initializeFinalDoc(){
outputStream=新的ByteArrayOutputStream();
Ddocument document=新文档();
复印机=新的PdfCopy(文档、输出流);
document.open();
}
公共字节[]getFinalDoc(){
document.close();
outputStream.close();
返回outputStream.toByteArray();
}
//打印单个文件后,它将与主控文档合并,以作为单个合并文档获得最终输出。
公共无效合并(字节[]每个文件)引发异常
{ 
如果(每个文件!=null)
{
PDF阅读器=新的PDF阅读器(每个文件);
PDF导入页面;
int numberOfPages=reader.getNumberOfPages();
对于(int i=0;i
我没有将所有内容添加到表中。 与最终文档合并后,pdf文件的大小似乎在增加。当我打印5000条记录时,最终的pdf文件有5000页,大小接近400Mb。知道为什么文件的大小会变大吗?我采用的方法有什么问题吗


更新2:我已经更新了示例代码。请原谅以前的错误。

我在这里提到我根据评论区的讨论所做的更改。这样这个问题就可以结束了,对其他人也会有帮助

  • 关闭代码中的所有资源,同时打印和合并内容,并使未使用的引用可供垃圾收集器使用
  • 如果内容有重复图像,请尝试使用
    PdfSmartCopy
    ,而不是使用
    PdfCopy
  • PdfSmartCopy尝试不向结果中添加同一对象两次,而是重新使用先添加的副本


    希望这有帮助。

    向我们展示一些代码,只是一个简单的概述。10000条记录算不了什么,你一定是做错了什么。iText 2.1.7是一个古老的版本,从那以后很多错误都被修复了。据我所知,即使是那个古老的州也能轻易地制作出10000页的PDF。因此,正如@PauloSoares所指出的,需要更多关于代码的细节。我希望您不要使用一个包含所有内容的大表。编辑后:我看不到您在
    merge
    中实例化
    outputStream
    。这仅仅是您的代码中缺少的,还是您在该方法中一次又一次地重复使用相同的
    ByteArrayOutputStream
    实例?在这种情况下,请注意,
    ByteArrayOutputStream.close
    是一种无操作方法,多次调用
    merge
    会导致一个巨大的备份
    byte[]
    。下次编辑后:确定,因此它不是错误的
    ByteArrayOutputStream
    使用。。。嗯。我看到您从
    pdfCopier
    中释放
    读卡器
    资源,但此后我没有看到您关闭
    读卡器
    。你试过了吗?我试过在合并文件后关闭阅读器。但这并没有带来任何改进。我正在寻找使用iText最新版本(v7)的解决方案。PdfSmartCopy在5.5.9版本中提供。