创建PDF时减少Java堆空间消耗

创建PDF时减少Java堆空间消耗,java,memory,memory-leaks,itext,Java,Memory,Memory Leaks,Itext,我对iText有问题 我正在创建包含大量图像的PDF,因此Java堆空间很容易用完 尝试使用Eclipse内存分析器分析dmp,发现每个映像使用大约10MB的堆空间。但是他们的硬盘只有大约350KB 是否有机会将堆刷新到HD并继续创建 是否存在其他常见泄漏 不幸的是,我还没有发现什么有用的东西 这就是堆对于一个图像的外观 一般来说,我认为添加的元素保留在缓存中。。。 我怎样才能把它们弄出来 有可能吗 这就是我当时使用的代码: Document document = new Document()

我对iText有问题

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

尝试使用Eclipse内存分析器分析dmp,发现每个映像使用大约10MB的堆空间。但是他们的硬盘只有大约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();
Document Document=新文档();
PdfWriter writer=null;
试一试{
writer=PdfWriter.getInstance(文档,新文件输出流(this.savePath));
}catch(filenotfounde异常){
e、 printStackTrace();
}捕获(文档异常){
e、 printStackTrace();
}
document.open();
段落pdfTitle=新段落();
添加(新短语(“标题”);
试一试{
文件。添加(pdfTitle);
document.add(Chunk.NEWLINE);
}捕获(文档异常){
e、 printStackTrace();
}
对于(int x=0;x<10;x++){
//章
段落章节名称=新段落(“章节”+x,字体[1]);
ChapterAutoNumber章=新ChapterAutoNumber(chapterName);
试一试{
文件.增补(第章);
}捕获(文档异常){
e、 printStackTrace();
}
对于(int y=0;y<10;y++){
//秒
段落段落名称=新段落(“段落”+y,字体[2]);
Section Section=章节.添加章节(章节名称);
对于(intz=0;z<10;z++){
//海底
小节=空;
图像=空;
试一试{
image=image.getInstance(路径);
}捕获(Badelement异常e){
e、 printStackTrace();
}捕获(格式错误){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
图像缩放率(50);
图像。设置压缩级别(9);
段落子描述=新段落(“描述”+z,字体[3]);
小节=节。添加节(子描述);
picSection.add(图像);
试一试{
文件。添加(第款);
}捕获(文档异常){
e、 printStackTrace();
}
}
}
}
document.close();

这里有一些有用的答案:


在将图像添加到PDF后,尝试将其设置为null?

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

第二种选择当然是增加应用程序的堆大小,前提是您有适当的硬件


为了以防万一,我应该提到内存泄漏的可能性。虽然在您的情况下,这似乎不太可能,但如果您需要它,它是存在的:)

100kB映像占用如此多内存的原因可能是因为它在磁盘上被压缩,而在内存中未压缩(原始)

Java应该进行垃圾收集,并且能够处理这个问题,除非您同时使用了太多的垃圾并且内存不足

这个问题涉及到清理使用过的内存


有时重用对象可以减少内存使用。您能否重复使用上一个PDF/Image对象并将下一个加载到其中。意思是不创建新对象?

我是iText的原始开发人员,我否决了你的问题,因为你的代码都错了

例如:您创建了一个chapter对象,但从未将其添加到文档中。相反,您正在添加一个没有在任何地方定义的picSection对象

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

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

如果您沉迷于使用Chapter类,请查看setComplete()方法,并定期将章节的一小部分添加到文档中,以便可以一点一点地释放对象。第一种方法(不使用Chapter类)远远优于第二种方法


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

您唯一的选择可能是使用更多内存。如今,一台32GB的机器不需要花那么多钱32 GB的PC内存成本约为250美元。如果我无法创建一个具有200 MB缓存的40页PDF,我不会尝试使用iText并行生成1000页PDF…每代PDF平均使用多少个内核?你们有多少核?假设答案是1.5和6,这意味着并发生成的pdf的最佳数量约为4(6/1.5)。从我的角度来看,这可能是年轻和缺乏经验的,我承认,租用EC2农场不是简单创建pdf的方式。。我想学习如何骑自行车而不是开法拉利…不确定EC2农场是否值得拥有。你可以租一台带有2个十六进制CPU和48 GB内存的服务器,每月租金为3500美元或90美元