PDFBox 打印时内存不足

Posted

技术标签:

【中文标题】PDFBox 打印时内存不足【英文标题】:PDFBox outofmemory when printing 【发布时间】:2017-04-24 08:15:00 【问题描述】:

我在使用默认打印机直接打印 PDF 文件的软件时遇到问题。有时我在用户打印 PDF 文件时收到 OutOfMemoryError 但我不知道是什么问题。

java.lang.OutOfMemoryError: Java heap space 
    at java.awt.image.DataBufferInt.<init>(Unknown Source) 
    at java.awt.image.Raster.createPackedRaster(Unknown Source) 
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(Unknown Source) 
    at java.awt.image.BufferedImage.<init>(Unknown Source) 
    at org.apache.pdfbox.pdmodel.graphics.color.PDDeviceGray.toRGBImage(PDDeviceGray.java:78) 
    at org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.from1Bit(SampledImageReader.java:216) 
    at org.apache.pdfbox.pdmodel.graphics.image.SampledImageReader.getRGBImage(SampledImageReader.java:142) 
    at org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject.getImage(PDImageXObject.java:340) 
    at org.apache.pdfbox.rendering.PageDrawer.drawImage(PageDrawer.java:793) 
    at org.apache.pdfbox.contentstream.operator.graphics.DrawObject.process(DrawObject.java:62) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:815) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:472) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:446) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.showForm(PDFStreamEngine.java:178) 
    at org.apache.pdfbox.contentstream.operator.graphics.DrawObject.process(DrawObject.java:70) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:815) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:472) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:446) 
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:149) 
    at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:189) 
    at org.apache.pdfbox.rendering.PDFRenderer.renderPage(PDFRenderer.java:208) 
    at org.apache.pdfbox.rendering.PDFRenderer.renderPageToGraphics(PDFRenderer.java:169) 
    at org.apache.pdfbox.printing.PDFPrintable.print(PDFPrintable.java:184) 
    at sun.print.RasterPrinterJob.printPage(Unknown Source) 
    at sun.print.RasterPrinterJob.print(Unknown Source)

我使用此代码通过 PDFBox 加载 PDF 文件并使用 Java 打印。

try (PDDocument doc = PDDocument.load(fileToPrint)) 

    PrinterJob job = PrinterJob.getPrinterJob();

    job.setJobName(jobName);
    job.setPageable(new PDFPageable(doc, Orientation.AUTO, false, 300));
    job.setPrintService(printerService);

    ...

    job.print(attributes);

    ...

 catch (IOException e) 
    ...
 catch (PrinterException e) 
    ...

PDFBox打印方法

@Test
   public void currentVersionTest() throws IOException, PrinterException 

      String jobName = testDocumentPdf.getFileName().toString();

      try (PDDocument doc = PDDocument.load(testDocumentPdf.toFile(), MemoryUsageSetting.setupTempFileOnly())) 

         PrinterJob job = PrinterJob.getPrinterJob();

         job.setJobName(jobName);
         job.setPageable(new PDFPageable(doc, Orientation.AUTO, false, 0));
         job.setPrintService(printService);

         PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
         attributes.add(Chromaticity.MONOCHROME);

         job.print(attributes);

      

      checkJobInQueue(jobName);
   

【问题讨论】:

【参考方案1】:

内存消耗取决于几个因素,例如图像数量、DPI 设置等。您可能需要调整应用程序的内存设置。

请查看https://pdfbox.apache.org/2.0/faq.html#outofmemoryerror 以获得一些改善内存需求/设置的建议。

【讨论】:

谢谢@Maruan Sahyoun,我会将代码改为使用PDDocument.load(file, MemoryUsageSetting.setupTempFileOnly()) 而不是PDDocument.load(file) 查看问题后我发现了一件事。当我发送打印 PDF 文件的作业时,我可以看到打印机队列上的大小,它太大了。例如,一个 268 页的文档会出现,大小约为 8 GB。这很奇怪,例如,如果使用 Foxit Reader 打印文档,大小约为 57 MB。文档的实际大小为 12 MB,我使用 Windows 7 检查作业大小。 @fjtorres 这很可能是因为文档在 Java 打印 API 打印之前已被光栅化。 @fjtorres 您可以将 dpi 参数设置为 0 而不是 300。这意味着矢量输出。但是 java 的内存使用会增加,因为打印机通常有 600 或 1200 dpi。 谢谢@TilmanHausherr。我用新的单元测试源代码编辑了这个问题。当我更改 300 而不是 0 时,打印机队列上的文档大小下降到 1GB。但是,当我使用 javax.print 包时,打印机队列中的打印大小比文件的实际大小要大一些,并且我没有检测到内存或 CPU 消耗的增量。我正在考虑更改代码以使用 javax.print 包而不是 PDFBox 和 java.awt.print 包。

以上是关于PDFBox 打印时内存不足的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用JAVA的时候老显示内存不足?

java总是提示内存不足

在C#中图像识别的时候出现内存不足的原因

windows7看图片提示内存不足

windows照片查看器无法显示此图片,因为计算机内存不足?

当我在 iOS 上继续游戏时,我的主菜单会内存不足吗?