我正在使用jPod合并我的PDF文档。我合并了每20页400个PDF,结果文件为190 MB,而单个pdf的大小为38 KB。我在IDE中检查了堆状态。我没有任何内存不足错误。我在拥有30个客户端的Apache Tomcat中运行了相同的程序。我的Tomcat停止处理请求。是因为jPod不使用Streaming 还是由于其他原因?
private void run() throws Throwable {
String sOutFileFullPathAndName = "/Users/test/Downloads/" + UUID.randomUUID().toString().replace("-", "");
PDDocument dstDocument = PDDocument.createNew();
for (int i = 0;i < 400; i++) {
//System.out.println(Runtime.getRuntime().freeMemory());
PDDocument srcDocument = PDDocument.createFromLocator(new FileLocator("/Users/test/Downloads/2.pdf") );
mergeDocuments(dstDocument, srcDocument);
}
FileLocator destinationLocator = new FileLocator(sOutFileFullPathAndName);
dstDocument.save(destinationLocator, null);
dstDocument.close();
}
private void mergeDocuments(PDDocument dstDocument, PDDocument srcDocument) {
PDPageTree pageTree = srcDocument.getPageTree();
int pageCount = pageTree.getCount();
for (int index = 0; index < pageCount; index++) {
PDPage srcPage = pageTree.getPageAt( index );
appendPage(dstDocument, srcPage);
srcPage = null;
}
}
private void appendPage(PDDocument document, PDPage page) {
PDResources srcResources = page.getResources();
CSContent cSContent = page.getContentStream();
PDPage newPage = (PDPage) PDPage.META.createNew();
// copy resources from source page to the newly created page
PDResources newResources = (PDResources) PDResources.META
.createFromCos(srcResources.cosGetObject().copyDeep());
newPage.setResources(newResources);
newPage.setContentStream(cSContent);
// add that new page to the destination document
document.addPageNode(newPage);
}
答案 0 :(得分:0)
PDF不仅仅是页面数据的“流”。它是一个复杂的数据结构,其中包含相互引用的对象。在这种具体情况下,页面树/节点,内容流,资源......
jPod仅使用弱引用将持久对象保留在内存中-始终可以从随机访问数据中刷新它们。如果开始更新对象结构,对象将被“锁定”在内存中,仅仅是因为更改不是持久的并且无法再刷新。
在不定期保存结果的情况下进行大量更改将使完整的结构保留在内存中-我认为这是您的问题。偶尔进行保存将减少内存占用。
此外,此算法将创建不良页树,该页树包含成千上万页的线性数组。您应该尝试创建平衡的树结构。优化的另一点是资源处理。合并字体或图像之类的资源可能会大大减小目标大小。