I wanted to investigate the memory usage of our Java application to see how much memory was being used for a task – in this case creating large BufferedImages from a PDF file.
Luckily, Java has an easy command Runtime.getRuntime() with 2 useful methods totalMemory() and freeMemory() – these give you the amount of memory usage in bytes. So this line will give you the current memory usage in Megabytes. I add it after the activity I want to test.
System.out.println("Meg used="+(Runtime.getRuntime().totalMemory()- Runtime.getRuntime().freeMemory())/(1000*1000)+"M");
This figure does not always give you the correct current usage, because it includes memory which was used but not free and can be reclaimed by garbage collection. You can request garbage collection with
System.gc();
but that does not guarantee that you will get the memory back immediately. I have added a loop to the end of my code and you can see the memory reappear as it waits.
Here are my usage figures.
Memory usage at start=11M
Memory usage after=46M
page 1 2550 4200 type=2
Memory usage after=46M
page 2 2550 4200 type=2
Memory usage after=46M
page 3 2550 4200 type=2
Memory usage after=46M
page 4 2550 4200 type=2
Memory usage at end=46M
Memory usage at end=3M
Memory usage at end=3M
Memory usage at end=3M
Note, the memory takes one iteration before I get all the memory back. So it is not exact (if you need this use a profiler) but it is quick and gives a good general idea.
When I generate a BufferedImage, a lot of the memory used up is just from the image object. To provide a better comparison, I reran the code just creating a blank image of the same size. Here are the figures.
Memory usage at start=12M
Memory usage after=45M
page 1 2550 4200 type=1
Memory usage after=45M
page 2 2550 4200 type=1
Memory usage after=45M
page 3 2550 4200 type=1
Memory usage after=45M
page 4 2550 4200 type=1
Memory usage at end=2M
So actually the overhead over of our code above the memory needed for the blank image is pretty good!
Here is the code if you would like to try some similar experiments with your Java application.
public class MemoryTest {
public static void main(String[] args){
if(args.length!=1)
System.out.println(“Please pass in filename”);
else{
MemoryTest test=new MemoryTest(args[0]);
}
}
public MemoryTest(String pdfFile){
PdfDecoder pdf=null;
try {
/**
* setup
*/
pdf = new PdfDecoder(true);
PdfDecoder.setFontReplacements(pdf);
pdf.openPdfFile(pdfFile);
int pageCount = pdf.getPageCount();
System.out.println(“Memory usage at start=”+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1000*1000)+”M”);
/**
* get the pages
*/
for (int currentPageNo = 1; currentPageNo <= pageCount; ++currentPageNo){
System.out.println(“”);
//action I want to investigate
BufferedImage imagePDF =new BufferedImage(2550,4200,1);//pdf.getPageAsHiRes(currentPageNo, null,false);
//BufferedImage imagePDF =pdf.getPageAsHiRes(currentPageNo, null,false);
pdf.flushObjectValues(true);
System.gc();
System.out.println(“Memory usage after=”+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1000*1000)+”M”);
if(imagePDF!=null){
System.out.println(“page “+currentPageNo+” “+imagePDF.getWidth()+” “+imagePDF.getHeight()+” type=”+imagePDF.getType());
}
imagePDF=null;
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(pdf!=null)
pdf.closePdfFile();
System.gc();
System.out.println(“Memory usage at end=”+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1000*1000)+”M”);
//endless loop so I can see memory freed and also see in my profiler
while(1==1){
try {
Thread.sleep(5000);
System.gc();
System.out.println(“Memory usage at end=”+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/(1000*1000)+”M”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Our software libraries allow you to
Convert PDF files to HTML |
Use PDF Forms in a web browser |
Convert PDF Documents to an image |
Work with PDF Documents in Java |
Read and write HEIC and other Image formats in Java |