我有两个 Java 应用程序,它们都使用大量内存,并且都使用 ImageIO.write()。到目前为止,这是我发现两者之间唯一的共同点。
一个在循环中调整图像大小。另一个循环下载图像并将它们保存到磁盘。以下是相关代码:
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)(在循环内)
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);
}
在这两种情况下,程序都会使用大量内存。就在 RAM 的演出周围。并且当循环结束时它不会被释放。在这两种情况下,我都有一个摆动 gui 运行。当图像保存全部完成并且 gui 只是空闲时,程序有时仍在使用 1Gb+ 的内存。我什至将swing gui不直接使用的每个变量都设置null
在循环之后。没有效果。
我错过了什么?
在此先感谢您的帮助。
更多信息:我刚刚在我的 IDE (Netbeans) 中分析了应用程序 1。我选择了应用程序一,因为它只处理 ImageIO(而不是网络 IO),所以这是一个更受控制的实验。
当程序在做它的事情(在循环中调整图像大小)时,总内存在大约 900,000,000 到 1,000,000,000 字节之间徘徊,而已用内存在给定时刻正在使用的总内存的大约 30% 到 50% 之间波动。
在 GC 上花费的时间从未超过 1%。
一旦实际调整大小完成并且程序进入“空闲”状态,就会发生两件事:1) 总内存停止波动并保持在 1,044,054,016 字节的静态,2) 已用内存下降到 ~14,000,000 字节 (14 mb) .
因此,看起来 JVM 只是没有归还它不再使用的内存空间。
同意?还是我误读了这个结果?