4

我遇到了 iText 的问题。

我正在创建包含大量图像的 PDF,因此 Java 堆空间很容易耗尽。

尝试使用 Eclipse Memory Analyzer 分析 dmp,发现每个图像使用大约 10MB 的堆空间。但他们在 HD 上只有大约 350KB

是否有机会将堆刷新到 HD 并继续创建?

还有其他常见的泄漏吗?

不幸的是,我还没有发现任何有用的东西。

堆

这就是一张图片的堆的样子

一般来说,我认为添加的元素保留在缓存中......我怎样才能把它们拿出来?

这样的事情可能吗?

那是我当时使用的代码:

Document document = new Document();
PdfWriter writer = null;
        try {
            writer = PdfWriter.getInstance(document, new FileOutputStream(this.savePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }

document.open();

Paragraph pdfTitle = new Paragraph();
pdfTitle.add(new Phrase("Title"));

try {
    document.add(pdfTitle);
    document.add(Chunk.NEWLINE);

} catch (DocumentException e) {
    e.printStackTrace();
}

for(int x = 0; x < 10; x++){
    //chapter
    Paragraph chapterName = new Paragraph("Chapter "+x, FONT[1]);
    ChapterAutoNumber chapter = new ChapterAutoNumber(chapterName);

    try {
    document.add(chapterhapter);
    } catch (DocumentException e) {
        e.printStackTrace();
    }

    for(int y = 0; y < 10; y++){
        //sec
        Paragraph sectionName = new Paragraph("Section "+y, FONT[2]);

        Section section  = chapter.addSection(sectionName);

        for(int z = 0; z < 10; z++){
            //subSec
            Section subSection = null;

            Image image = null;
            try {
            image = Image.getInstance(path);
            } catch (BadElementException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            image.scalePercent(50);

            image.setCompressionLevel(9);
            Paragraph subDesc = new Paragraph("Desc "+z, FONT[3]);

            subSection = section.addSection(subDesc);

            picSection.add(image);

            try {
                document.add(subSection);
            } catch (DocumentException e) {
                e.printStackTrace();
            }

        }

    }

}

document.close();
4

4 回答 4

2

我是 iText 的原始开发人员,我对你的问题投了反对票,因为你的代码全错了。

例如:您创建了一个章节对象,但您从未将它添加到文档中。相反,您要添加一个未在任何地方定义的 picSection 对象。

然而,我的主要批评是,您使用的是实现 LargeElement 接口的 ChapterAutoNumber 对象,并抱怨内存使用。这就像在说:每天我吃一罐蛋黄酱,我都在想:我怎么这么胖?

你为什么使用章节/章节?如果书签是选择这些对象的主要原因,如果你想减少使用的内存,你应该切换到使用 PdfOutline。因为现在,您通过将它们添加到 Chapter 对象来构建大量对象,而这些对象只能在您将章节添加到文档时释放。在此之前,进行垃圾收集是没有用的,因为垃圾收集器无法丢弃存储在 Chapter 对象中的内容。

如果你沉迷于使用 Chapter 类,可以看看 setComplete() 方法,定期将章节的一小部分添加到文档中,这样对象就可以一点一点的释放出来。第一种方法(不使用 Chapter 类)比第二种方法好得多。

如果我看到更多这样的问题,我可能会决定从 iText 中删除 Chapter/Section 类。

于 2012-09-10T11:45:33.860 回答
1

这里有一些有用的答案:Java heap space out of memory

尝试将图像附加到 PDF 后将其设置为空?

于 2012-09-06T10:39:11.463 回答
1

我的第一个猜测是搜索 iText 文档以获取某种流媒体支持。有没有办法不将正在创建的整个 PDF 存储在内存中?实时调频。

第二种选择当然是增加应用程序的堆大小,如果你有合适的硬件的话。

而且,以防万一,我应该提到内存泄漏的可能性。尽管在您的情况下似乎不太可能,但如果您需要,可以使用 Plumbr :)

于 2012-09-07T06:36:50.253 回答
1

100kB 的图像占用这么多内存的原因可能是因为它在磁盘上被压缩而在内存中未压缩(原始)。

Java 应该进行垃圾收集并且能够使用它,除非您同时使用太多并且内存不足。

这个问题涉及清理使用的内存;Java 堆溢出,强制垃圾回收

有时重用对象会减轻内存使用量。你能重新使用最后一个 PDF/Image 对象并将下一个加载到其中吗?意思而不是创建一个新对象?

于 2012-09-10T08:02:44.273 回答