java - Apache PDFBOX - 使用 split(PDDocument 文档)时出现 java.lang.OutOfMemoryError

标签 java pdfbox

我正在尝试使用 Apache PDFBOX API V2.0.2 拆分一个 300 页左右的文档。 尝试使用以下代码将 pdf 文件拆分为单页时:

        PDDocument document = PDDocument.load(inputFile);
        Splitter splitter = new Splitter();
        List<PDDocument> splittedDocuments = splitter.split(document); //Exception happens here

我收到以下异常

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

这表明 GC 花费了很长时间来清除堆,而回收的数量并不合理。

有很多 JVM 调优方法可以解决这个问题,但是这些都只是治标不治本。

最后一点,我使用的是 JDK6,因此在我的情况下使用新的 java 8 Consumer 不是一个选择。谢谢

编辑:

这不是 http://stackoverflow.com/questions/37771252/splitting-a-pdf-results-in-very-large-pdf-documents-with-pdfbox-2-0-2 的重复问题:

 1. I do not have the size problem mentioned in the aforementioned
    topic. I am slicing a 270 pages 13.8MB PDF file and after slicing
    the size of each slice is an average of 80KB with total size of
    30.7MB.
 2. The Split throws the exception even before it returns the splitted parts.

我发现只要我不传递整个文档,分割就可以通过,而是将其作为“批处理”传递,每个批处理 20-30 页,这样就可以完成工作。

最佳答案

PDF Box 将拆分操作产生的部分作为 PDDocument 类型的对象以对象形式存储在堆中,这会导致堆很快被填满,即使在循环中的每一轮之后调用 close() 操作,GC 仍然无法以与填满相同的方式回收堆大小。

一个选项是将文档拆分操作拆分为多个批处理,其中每个批处理是一个相对可管理的 block (10 到 40 页)

public void execute() {
    File inputFile = new File(path/to/the/file.pdf);
    PDDocument document = null;
    try {
        document = PDDocument.load(inputFile);

        int start = 1;
        int end = 1;
        int batchSize = 50;
        int finalBatchSize = document.getNumberOfPages() % batchSize;
        int noOfBatches = document.getNumberOfPages() / batchSize;
        for (int i = 1; i <= noOfBatches; i++) {
            start = end;
            end = start + batchSize;
            System.out.println("Batch: " + i + " start: " + start + " end: " + end);
            split(document, start, end);
        }
        // handling the remaining
        start = end;
        end += finalBatchSize;
        System.out.println("Final Batch  start: " + start + " end: " + end);
        split(document, start, end);

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        //close the document
    }
}

private void split(PDDocument document, int start, int end) throws IOException {
    List<File> fileList = new ArrayList<File>();
    Splitter splitter = new Splitter();
    splitter.setStartPage(start);
    splitter.setEndPage(end);
    List<PDDocument> splittedDocuments = splitter.split(document);
    String outputPath = Config.INSTANCE.getProperty("outputPath");
    PDFTextStripper stripper = new PDFTextStripper();

    for (int index = 0; index < splittedDocuments.size(); index++) {
        String pdfFullPath = document.getDocumentInformation().getTitle() + index + start+ ".pdf";
        PDDocument splittedDocument = splittedDocuments.get(index);

        splittedDocument.save(pdfFullPath);
    }
}

关于java - Apache PDFBOX - 使用 split(PDDocument 文档)时出现 java.lang.OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53508589/

相关文章:

java - Eclipse 中 Gradle 任务的 Stacktrace 选项

.net - PDFBox - 使用 IKVM 构建最新版本的 .NET

java - 使用 PDFBox 2.0.12 进行外部签名

java - 是否可以在 PDFBOX 中调整文本?

java - 如何为复选框添加边框并使其始终可见

java - 子类是否继承接口(interface)?

java - SpringJUnit4ClassRunner 在 Spring5 中损坏了吗?

java - 是否可以在 Crashlytics 中自定义 CrashDialog?

java - 向 CustomUsersCredentials 添加新密码,是好主意还是坏主意?

pdf - 计算pdf中(Td,TD,Tm,cm,T*)内容流的确切位置?