首页 > 解决方案 > 使用 PDFBox AnnotationconstructAppearances() 方法获取 OutOfMemoryError

问题描述

简而言之

我一直在开发一个获取 pdf 的程序,突出显示一些单词(通过 pdfbox Mark Annotation)并保存新的 pdf。

为了使这些注释在某些查看器(如pdf.js )上可见,需要在将标记注释添加到页面注释列表之前调用 pdAnnotationTextMarkup.constructAppearances()。

但是,通过这样做,在处理包含数千个标记注释的大型文档时,我得到了 OutOfMemoryError。

我想知道是否有办法防止这种情况发生。

(这是这张票的一种续集,但这与这张票的关系不大)

技术规格:

PDFBox 2.0.17
Java 11.0.6+10, AdoptOpenJDK
MacOS Catalina 10.15.2, 16gb, x86_64

我的代码

//my pdf has 216 pages     
for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++) {
    PDPage page = document.getPage(pageIndex);
    List<PDAnnotation> annotations = page.getAnnotations();

    // each coordinate obj represents a hl annotation. crashing with 7.816 elements
    for (CoordinatePoint coordinate : coordinates) {
        PDAnnotationTextMarkup txtMark = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
        txtMark.setRectangle(pdRectangle);
        txtMark.setQuadPoints(quadPoints);
        txtMark.setColor(getColor());
        txtMark.setTitlePopup(coordinate.getHintDescription());
        txtMark.setReadOnly(true);

        // this is what makes everything visible on pdf.js and what causes the Java heap space error
        txtMark.constructAppearances();

        annotations.add(txtMark);
    }
}

当前结果

这是导致问题的繁重 pdf 文档: https ://pdfhost.io/v/I~nu~.6G_French_Intensive_Care_Society_International_congress_Ranimation_2016.pdf

我的程序尝试在216页中添加7.816 个注释。

和堆栈跟踪:

[main] INFO highlight.PDFAnnotation - Highlighting 13613_2016_Article_114.pdf...
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at org.apache.pdfbox.io.ScratchFile.<init>(ScratchFile.java:128)
    at org.apache.pdfbox.io.ScratchFile.getMainMemoryOnlyInstance(ScratchFile.java:143)
    at org.apache.pdfbox.cos.COSStream.<init>(COSStream.java:61)
    at org.apache.pdfbox.pdmodel.interactive.annotation.handlers.PDAbstractAppearanceHandler.createCOSStream(PDAbstractAppearanceHandler.java:106)
    at org.apache.pdfbox.pdmodel.interactive.annotation.handlers.PDHighlightAppearanceHandler.generateNormalAppearance(PDHighlightAppearanceHandler.java:136)
    at org.apache.pdfbox.pdmodel.interactive.annotation.handlers.PDHighlightAppearanceHandler.generateAppearanceStreams(PDHighlightAppearanceHandler.java:59)
    at org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup.constructAppearances(PDAnnotationTextMarkup.java:175)
    at org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup.constructAppearances(PDAnnotationTextMarkup.java:147)
    at highlight.PDFAnnotation.drawHLAnnotations(PDFAnnotation.java:288)

我已经尝试将我的 jvm xmx 和 xms 参数增加到 like -Xmx10g -Xms10g,这只会稍微推迟崩溃。

我想要的是

我想防止这个内存问题,并且仍然能够在 pdf.js 查看器中看到我的注释。如果不调用constructAppearances,这个过程会快得多,我没有这个问题,但是注释只能在一些pdf查看器上看到,比如Adobe。

有什么建议么?我在这里做错了什么或遗漏了什么吗?

标签: javapdfpdfbox

解决方案


在即将发布的 2.0.19 版本中,构建如下外观:

annotation.constructAppearances(document);

在 2.0.18 及更早版本中,您需要自己初始化外观处理程序:

setCustomAppearanceHandler(new PDHighlightAppearanceHandler(annotation, document));

该行可以在 2.0.19 中删除,因为这是默认的外观处理程序。

为什么这一切?这样在注释处理程序中使用文档公共内存空间(“临时文件”)而不是每次都创建一个新空间(很大)。后者在调用new COSStream()而不是 时完成document.getDocument().createCOSStream()

当然,所有这些仅在进行许多注释时才重要。

相关 PDFBox 问题:PDFBOX-4772PDFBOX-4080


推荐阅读