Memory management 在打印和合并pdf文件时,将iText与Java结合使用以避免内存泄漏和不必要的内存消耗的最佳做法是什么
我正在使用iText 2.1.7库创建pdf报告。所有页面中只有两个小日志作为图像内容。Rest是所有文本和表格内容。我将图像设置为单例,以避免图像使用额外的内存。这似乎可以很好地处理多达10000条记录。但除此之外,堆正在耗尽空间。当前堆大小设置为1Gb 在执行pdf生成时,是否有其他优化可以减少内存消耗 更新1:添加更多详细信息和代码 我的要求是为每个记录打印单独的pdf文件,并将它们合并到一个pdf文件中作为最终输出。为了减少内存使用,我正在批量加载数据,并在加载下一批数据之前执行“打印+合并”。我使用的方法如下所示: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文件中作为最终输出。为了减少内存使用,我正在批量加载数据,并在加载下一批数据之前执行“打印+
// 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
希望这有帮助。向我们展示一些代码,只是一个简单的概述。10000条记录算不了什么,你一定是做错了什么。iText 2.1.7是一个古老的版本,从那以后很多错误都被修复了。据我所知,即使是那个古老的州也能轻易地制作出10000页的PDF。因此,正如@PauloSoares所指出的,需要更多关于代码的细节。我希望您不要使用一个包含所有内容的大表。编辑后:我看不到您在
merge
中实例化outputStream
。这仅仅是您的代码中缺少的,还是您在该方法中一次又一次地重复使用相同的ByteArrayOutputStream
实例?在这种情况下,请注意,ByteArrayOutputStream.close
是一种无操作方法,多次调用merge
会导致一个巨大的备份byte[]
。下次编辑后:确定,因此它不是错误的ByteArrayOutputStream
使用。。。嗯。我看到您从pdfCopier
中释放读卡器
资源,但此后我没有看到您关闭读卡器
。你试过了吗?我试过在合并文件后关闭阅读器。但这并没有带来任何改进。我正在寻找使用iText最新版本(v7)的解决方案。PdfSmartCopy在5.5.9版本中提供。