views:

1698

answers:

3

I am trying to merge 1000 PDF Files thru iText. I am not sure where the memory leakage is happening. Below is the sample code. Note that i am removing the child-pdf file as soon as i merge to the parent file. Please pointout bug in below code or is there any better way to do this with out memory conception. This process is done thru servlet (not standalone program)

FileInputStream local_fis = null;
BufferedInputStream local_bis = null;
File localFileObj = null;
for(int taIdx=0;taIdx<totalSize;taIdx++){
    frObj = (Form3AReportObject)reportRows.get(taIdx);
    localfilename = companyId + "_" +  frObj.empNumber + ".pdf";

    local_fis = new FileInputStream(localfilename);
    local_bis = new BufferedInputStream(local_fis); 
    pdfReader = new PdfReader(local_bis);

    cb = pdfWriter.getDirectContent(); 
    document.newPage();
    page = pdfWriter.getImportedPage(pdfReader, 1);
    cb.addTemplate(page, 0, 0);
    local_bis.close();
    local_fis.close();

    localFileObj = new File(localfilename);
    localFileObj.delete();
}
document.close();
+1  A: 

Have you tried increasing max heap size from the default (which is only 64mb)?

See:

matt b
Increasing heap size wont help. Because this process will run in Servlet environment and several request may come. So we need to find out the memory leakage.
Niger
And what leads you to say that? How do you know that your current settings are good enough? Have you analyzed the memory needs of this code and the application as a whole?
matt b
I am thinking the current settings is good enough and the current code "must" work efficiently with this settings as i am writing page by page in to the stream (not storing in memory)
Niger
That doesn't make much sense - if the current settings were good enough, then why are you getting OutOfMemoryErrors? It looks like you add more objects/data onto your pdfWriter and PDF document with each iteration. This implies that it is growing in size per PDF.
matt b
Instead of assuming that a solution wouldn't work, how about experimenting with it and finding out for sure? The question about increasing max heap size from the default was meant to be the first troubleshooting step. When you are having heap size issues, the first step on any checklist has to be "have you changed the settings from the default?"
matt b
No i didn't try increasing the heap size. I will try that and also i will try "Michael Rutherfurd's" idea.
Niger
Hello Matt, Please check out the below comment. The code runs without increasing HEAP Size.
Niger
+2  A: 

Who says there is a memory leak? Your merged document needs to fit into memory in its entirety, there's no way around it, and it may well be larger than the default heap size of 64MB in memory (rather than on disc).

I don't see a problem with your code, but if you want to diagnose it in detail, use visualvm's heap profiler (comes with the JDK since Java 6 update 10 or so).

Michael Borgwardt
Thanks for your suggesion Micheal. I will check heap profiler and update my findings
Niger
Hey Micheal i tried to use visualvm but cannot connect to remote. Started a new thread for this http://stackoverflow.com/questions/1263991/conntecting-remote-tomcat-jmx-instance-using-jconsole
Niger
+2  A: 

You might want to try something like the following (exception handling, file close and delete removed for clarity):

for(int taIdx = 0; taIdx < totalSize; taIdx++) {
    Form3AReportObject frObj = (Form3AReportObject)reportRows.get(taIdx);

    localfilename = companyId + "_" +  frObj.empNumber + ".pdf";

    FileInputStream local_fis = new FileInputStream(localfilename);

    pdfWriter.freeReader(new PdfReader(local_fis));

    pdfWriter.flush();
}

pdfWriter.close();
Michael Rutherfurd
Excellent!! here is where the memory leak was. The missing line was pdfWriter.freeReader().Now no need to increase the javaheap. It works. Thanks
Niger
I found one more solution without using pdfwriter. for(int taIdx=0;taIdx<totalSize;taIdx++){ frObj = (Form3AReportObject)reportRows.get(taIdx); localfilename = companyId + "_" + frObj.empNumber + ".pdf"; PdfReader reader = new PdfReader(localfilename); document.setPageSize(reader.getPageSizeWithRotation(1)); PdfImportedPage pdfImportedPage = pdfCopy.getImportedPage(reader, 1); pdfCopy.addPage(pdfImportedPage); reader.close(); }
Niger