编辑大型PDF时,iText7(PDFSweep)抛出内存错误

编辑大型PDF时,iText7(PDFSweep)抛出内存错误,itext,Itext,我试图使用PDFSweep从PDF中删除一些内容,以下是我代码的一部分,我正在使用CompositeCleanupStrategy并将RegexBasedCleanupStrategy添加到策略中: CompositeCleanupStrategy strategy = new CompositeCleanupStrategy(); for (int i = 0; i < keywordlist.size(); i++) { String kvalue =

我试图使用PDFSweep从PDF中删除一些内容,以下是我代码的一部分,我正在使用CompositeCleanupStrategy并将RegexBasedCleanupStrategy添加到策略中:

    CompositeCleanupStrategy strategy = new CompositeCleanupStrategy();
    for (int i = 0; i < keywordlist.size(); i++) {

        String kvalue = keywordlist.get(i);


        Loger.getLogger().info("keyword " + i + "=" + kvalue);

        strategy.add(new RegexBasedCleanupStrategy(kvalue).setRedactionColor(ColorConstants.GRAY));

    }

   try {
        PdfWriter writer = new PdfWriter(dest);
        writer.setCompressionLevel(0);
        PdfDocument pdf = new PdfDocument(new PdfReader(src), writer);
        // sweep
        PdfAutoSweep pdfAutoSweep = new PdfAutoSweep(strategy);

        pdfAutoSweep.cleanUp(pdf);

        // close the document
        pdf.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
CompositeCleanupStrategy策略=新的CompositeCleanupStrategy();
对于(int i=0;i
当stragety很小时,比如只有一个或两个,清理工作正常,但是如果关键字列表中有243个,PDF大小约为70MB,我得到以下错误:

 Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit 
 exceeded
at java.lang.String.toLowerCase(String.java:2590)
at java.lang.String.toLowerCase(String.java:2670)
at com.itextpdf.io.font.PdfEncodings.convertToString(PdfEncodings.java:287)
at com.itextpdf.kernel.pdf.PdfString.toUnicodeString(PdfString.java:163)
at com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getUnscaledBaselineWithOffset(TextRenderInfo.java:425)
at com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getBaseline(TextRenderInfo.java:213)
at com.itextpdf.kernel.pdf.canvas.parser.listener.CharacterRenderInfo.<init>(CharacterRenderInfo.java:112)
at com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.toCRI(RegexBasedLocationExtractionStrategy.java:156)
at com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.eventOccurred(RegexBasedLocationExtractionStrategy.java:135)
at com.itextpdf.pdfcleanup.autosweep.CompositeCleanupStrategy.eventOccurred(CompositeCleanupStrategy.java:115)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.eventOccurred(PdfCanvasProcessor.java:534)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.displayPdfString(PdfCanvasProcessor.java:549)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.access$4700(PdfCanvasProcessor.java:108)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor$ShowTextArrayOperator.invoke(PdfCanvasProcessor.java:617)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.invokeOperator(PdfCanvasProcessor.java:452)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processContent(PdfCanvasProcessor.java:281)
at com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processPageContent(PdfCanvasProcessor.java:302)
at com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:77)
at com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:90)
at com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.getPdfCleanUpLocations(PdfAutoSweep.java:130)
at com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.cleanUp(PdfAutoSweep.java:186)
线程“main”java.lang.OutOfMemoryError中的异常:GC开销限制 超过 位于java.lang.String.toLowerCase(String.java:2590) 位于java.lang.String.toLowerCase(String.java:2670) 位于com.itextpdf.io.font.PdfEncodings.convertToString(PdfEncodings.java:287) 在com.itextpdf.kernel.pdf.PdfString.toUnicodeString(PdfString.java:163) 位于com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getUnscaledBaselineWithOffset(textrederInfo.java:425) 在com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo.getBaseline(TextRenderInfo.java:213)上 位于com.itextpdf.kernel.pdf.canvas.parser.listener.CharacterRenderInfo.(CharacterRenderInfo.java:112) 在com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.toCRI(RegexBasedLocationExtractionStrategy.java:156) 在com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy.EventOccursed(RegexBasedLocationExtractionStrategy.java:135) 在com.itextpdf.pdfcleanup.autosweep.compositeleanupstrategy.eventoccurrent上(compositeleanupstrategy.java:115) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.eventoccurrent(PdfCanvasProcessor.java:534) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.displayPdfString(PdfCanvasProcessor.java:549) com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.access$4700(PdfCanvasProcessor.java:108) 在com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor$ShowTextArrayOperator.invoke(PdfCanvasProcessor.java:617)上 位于com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.invokeOperator(PdfCanvasProcessor.java:452) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processContent(PdfCanvasProcessor.java:281) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor.processPageContent(PdfCanvasProcessor.java:302) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:77) 位于com.itextpdf.kernel.pdf.canvas.parser.PdfDocumentContentParser.processContent(PdfDocumentContentParser.java:90) 位于com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.getPdfCleanUpLocations(PdfAutoSweep.java:130) 位于com.itextpdf.pdfcleanup.autosweep.PdfAutoSweep.cleanUp(PdfAutoSweep.java:186)
(完全披露:此处为
RegexBasedCleanupStrategy
的原始作者)

RegexBasedCleanupStrategy
不是这样使用的。 您正在创建该类的200个实例,所有这些实例都将在文档中查看它们是否可以(逐块)将PDF与正则表达式相匹配

为了做到这一点,他们将在文档中存储所有块,对它们进行排序,然后循环遍历它们

因此,您在内存中将文档复制了200多次。 这是你的瓶颈

我的建议是:构建一个更好的正则表达式。 显然,您可以将关键字a、b、c等与正则表达式匹配

(a)|(b)|(c)

这将只在内存中复制文档一次,然后尝试将聚合正则表达式与之匹配

它既有性能优势,又有内存占用优势。

(完整披露:此处为
RegexBasedCleanupStrategy
的原始作者)

RegexBasedCleanupStrategy
不是这样使用的。 您正在创建该类的200个实例,所有这些实例都将在文档中查看它们是否可以(逐块)将PDF与正则表达式相匹配

为了做到这一点,他们将在文档中存储所有块,对它们进行排序,然后循环遍历它们

因此,您在内存中将文档复制了200多次。 这是你的瓶颈

我的建议是:构建一个更好的正则表达式。 显然,您可以将关键字a、b、c等与正则表达式匹配

(a)|(b)|(c)

这将只在内存中复制文档一次,然后尝试将聚合正则表达式与之匹配


它同时具有性能和内存占用优势。

您是否尝试过为虚拟机提供更多内存?是的,4 Gb,仍然会出现错误。您是否尝试过为虚拟机提供更多内存?是的,4 Gb,仍然会出现错误。Joris,感谢您的回复和解释,但是关键字我试图编辑的是一个独特的单词列表,很难合并到一个正则表达式中,如果我编辑错误的单词将会失败;其次,如果我使用RegexBasedCleanupStrategy,它将创建200个实例,我很惊讶,我认为如果我使用CompositeCleanupStrategy,并添加不同的策略,它应该只加载PDF(文本)一次,然后应用该策略;在这种情况下,我不得不牺牲性能,一次只执行一个RegexBasedCleanUpstrate,至少不会出现OOM错误。您还可以创建自己的RegexBasedCleanupStrat版本