我正在开发一个Java项目。 我从服务器检索pdf并将其转换为图像,以将像素与预期文件进行比较。 当我只用20-30个文件运行它时程序很好,但是当我尝试使用超过30个文件时,它会抛出OutOfMemoryError。
好像是pdf - >图像转换方法正在产生OutOfMemoryError。
以下是方法:
PDDocument document = null;
try {
document = PDDocument.loadNonSeq(new File(pdfFile), null);
List<PDPage> pages = new ArrayList<PDPage>();
for (Object obj : document.getDocumentCatalog().getAllPages()) {
PDPage page = (PDPage) (obj);
pages.add(page);
}
int pageNum = 0;
for (PDPage pdPage : pages) {
BufferedImage img = pdPage.convertToImage(BufferedImage.TYPE_INT_RGB, 100);
if (isExpected) {
ImageIOUtil.writeImage(img, FolderUtils.getImageFolder(websiteName) + File.separator + "expected"
+ (++pageNum) + ".png", 100);
} else {
ImageIOUtil.writeImage(img, FolderUtils.getImageFolder(websiteName) + File.separator + "rendered"
+ (++pageNum) + ".png", 100);
}
img.flush();
img = null;
}
} catch (IOException e) {
debugLog.log(Level.SEVERE, e.getMessage(), e);
} finally {
if (document != null) {
try {
document.close();
document = null;
} catch (IOException e) {
debugLog.log(Level.SEVERE, e.getMessage(), e);
}
}
}
这是Java堆空间日志的一部分:
Exception in thread "pool-1-thread-1" java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferInt.<init>(DataBufferInt.java:75)
at java.awt.image.Raster.createPackedRaster(Raster.java:467)
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1032)
at java.awt.image.BufferedImage.<init>(BufferedImage.java:340)
at org.apache.pdfbox.pdmodel.graphics.xobject.CompositeImage.createMaskedImage(CompositeImage.java:85)
at org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage.applyMasks(PDXObjectImage.java:158)
at org.apache.pdfbox.pdmodel.graphics.xobject.PDPixelMap.getRGBImage(PDPixelMap.java:367)
at org.apache.pdfbox.util.operator.pagedrawer.Invoke.process(Invoke.java:87)
at org.apache.pdfbox.util.PDFStreamEngine.processOperator(PDFStreamEngine.java:557)
at org.apache.pdfbox.util.PDFStreamEngine.processSubStream(PDFStreamEngine.java:268)
at org.apache.pdfbox.util.PDFStreamEngine.processSubStream(PDFStreamEngine.java:235)
at org.apache.pdfbox.util.PDFStreamEngine.processStream(PDFStreamEngine.java:215)
at org.apache.pdfbox.pdfviewer.PageDrawer.drawPage(PageDrawer.java:139)
at org.apache.pdfbox.pdmodel.PDPage.convertToImage(PDPage.java:801)
at ********************.convertPDFToImages(Processor.java:107)
at ********************.APIProcessor.run(APIProcessor.java:62)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
以下是GC开销限制的日志部分超出:
Exception in thread "pool-1-thread-3" java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.Collections.singletonList(Collections.java:3349)
at org.apache.pdfbox.pdfparser.NonSequentialPDFParser.parseDictObjects(NonSequentialPDFParser.java:1275)
at org.apache.pdfbox.pdfparser.NonSequentialPDFParser.initialParse(NonSequentialPDFParser.java:414)
at org.apache.pdfbox.pdfparser.NonSequentialPDFParser.parse(NonSequentialPDFParser.java:886)
at org.apache.pdfbox.pdmodel.PDDocument.loadNonSeq(PDDocument.java:1273)
at org.apache.pdfbox.pdmodel.PDDocument.loadNonSeq(PDDocument.java:1256)
at *********************.convertPDFToImages(Processor.java:99)
at ********************.APIProcessor.run(APIProcessor.java:62)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
此外,第一个Java堆空间错误发生在id22,第二个错误发生在id33。
我在MAVEN_OPTS=-d64 -Xms500M -Xmx7000M -XX:PermSize=65M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Temp\heapDump.txt -Xdebug -Xrunjdwp:transport=dt_socket,address=8123,server=y,suspend=n
我可以请求帮助解决我的代码有什么问题吗?或者是什么原因引起了这个问题?有内存泄漏吗?
P.S。:以下是渲染的pdf文件和JConsole屏幕截图的链接: https://www.dropbox.com/sh/86gxnmnk5gl66k6/AAAFE_lapBr3cH8EMlXu94qJa?dl=0
另外,我现在在8GB RAM服务器上运行该程序。但如果我在本地16GB RAM笔记本电脑上运行它,就没有java堆空间错误。
答案 0 :(得分:-1)
我们确实在PDFBox图像转换方面遇到了一些问题。它通过缓冲图像消耗了大量的堆空间,并且是一个定时炸弹,因为它增加了生成页面的数量。
我们的解决方案是改变库。我们确实用JPedal获得了良好的性能,如果事情没有改变,他们确实有他们框架的LGPL版本。