Получение OutOfMemoryError с помощью метода PDFBox Annotation constructAppearances () - PullRequest
0 голосов
/ 12 февраля 2020

В двух словах

Я работал над программой, которая получает 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, 16 ГБ, 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-файл c, что приводит к проблеме: https://pdfhost.io/v/I~nu~.6G_French_Intensive_Care_Society_International_congress_Ranimation_2016.pdf

Моя программа пытается добавить 7.816 аннотаций к ней на всех страницах 216 .

и трассировка стека:

[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 до -Xmx10g -Xms10g, что лишь немного отложило cra sh.

Что я хочу

Я хочу предотвратить эту проблему с памятью и по-прежнему иметь возможность просматривать свои комментарии в pdf. js Просмотрщик. Без вызова constructAppearances процесс намного быстрее, у меня нет этой проблемы, но аннотации можно увидеть только в некоторых средствах просмотра PDF, таких как Adobe.

Есть предложения? Я что-то здесь не так делаю или что-то упускаю?

1 Ответ

2 голосов
/ 13 февраля 2020

В следующей версии 2.0.19 создайте внешний вид следующим образом:

annotation.constructAppearances(document);

В 2.0.18 и более ранних версиях вам нужно самостоятельно инициализировать обработчик внешнего вида:

setCustomAppearanceHandler(new PDHighlightAppearanceHandler(annotation, document));

Эта строка может быть удалена в 2.0.19, так как это обработчик внешнего вида по умолчанию.

Зачем все это? Таким образом, общая область памяти документа («рабочий файл») используется в обработчике аннотаций вместо того, чтобы каждый раз создавать новую (которая является большой). Последнее делается при вызове new COSStream() вместо document.getDocument().createCOSStream().

Все это, конечно, важно только при выполнении множества аннотаций.

связанные с PDFBox проблемы: PDFBOX-4772 и PDFBOX-4080

...