I have two Java applications that both use a ton of memory, and both use ImageIO.write(). So far, that is the only thing I have found in common between the two.
One resizes images in a loop. The other downloads images in a loop and saves them to disk. Here's the relevant code:
1)
for(File imageFile : imageFilesList)
{
if(!stillRunning) return;
File outputFile = new File(imageFile.getAbsolutePath().replace(sourceBaseFolder.getAbsolutePath(), destinationFolder.getAbsolutePath()));
try
{
outputFile.mkdirs();
BufferedImage inputImage = ImageIO.read(imageFile);
BufferedImage resizedImage = ImageResizer.resizeImage(inputImage, maxHeight, maxWidth);
ImageIO.write(resizedImage, "jpg", outputFile);
}
catch(IOException ex)
{
userInterface.displayMessageToUser("IOException ocurred while converting an image: " + ex.getLocalizedMessage());
System.out.println(outputFile.getAbsolutePath());
ex.printStackTrace();
return;
}
imagesConverted++;
userInterface.updateTotalConvertedImages(++convertedFiles);
}
2) (inside a loop)
try
{
u = new URL(urlString);
uc = u.openConnection();
uc.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
uc.connect();
uc.getInputStream();
in = uc.getInputStream();
BufferedImage tempImage = ImageIO.read(in);
String fileName = fn = ImageDownload.getFileName(u.getPath());
fileName = outputDirString + FILE_SEPARATOR + fileName;
while (new File(fileName).exists())
{
fileName = appendCopyIndicator(fileName);
}
ImageIO.write(tempImage, "jpg", new File(fileName));
parent.notifyOfSuccessfulDownload(fn);
in.close();
}
catch (FileNotFoundException ex)
{
parent.notifyOfFailedDownload(fn);
}
catch (IOException ex)
{
parent.handleException(ex);
}
In both cases, the program uses a lot of memory. Right around a gig of RAM. And it doesn't get freed up when the loop is over. In both cases I have a swing gui running. When the image saving is all done and the gui is just idling, the program is still using sometimes 1Gb+ of memory.
I have gone so far as to set every variable not directly used by the swing gui to null
after the loop. To no effect.
What am I missing?
Thanks in advance for your help.
More information: I just profiled application 1 in my IDE (Netbeans). I chose application one because it only deals with ImageIO (and not network IO), so it's a more controlled experiment.
While the program was doing its thing (resizing images in a loop), the Total Memory hovered between roughly 900,000,000 ~ 1,000,000,000 bytes, while the Used Memory fluxuated between roughly 30% and 50% of the Total Memory being used at a given moment.
And time spent in GC never went above 1%.
As soon as the actual resizing was finished and the program went into "idle", two things happened: 1) The Total Memory stopped fluxuating and stayed static at 1,044,054,016 bytes, and 2) the Used Memory dropped to ~14,000,000 bytes (14 mb).
So, it looks like the JVM is just not giving back memory space that it's no longer using.
Agree? Or am I misreading this result?