我有一个程序,可以打开一些8k图像并将其大小调整为200x200像素。 该程序运行良好,但问题是关闭每个图像后它不会释放内存,因此它会很快耗尽内存! (在收到40张图片之后)
我已经尝试使用system.gc()将图像刷新并将其设置为null,而且我也不能使用ImageReader,因为图像格式不正确,并且说jpeg图像不是以0x01 0x11和其他一些数字开头。同时启用禁用ImageIO.usecatch也无济于事。我尝试对图像使用全局变量,但也无济于事。
我需要在线程中运行程序,但是在编辑某些图像后,即使在单个线程上,它也会占用过多的内存。 我删除了我确认与问题无关的多余代码。
static public class ImageLoadingTask implements Callable<JPanel> {
private final URL url;
private final int i;
private final JPanel scrollPane;
ImageLoadingTask(int i, URL url, JPanel scrollPane) {
this.url = url;
this.i = i;
this.scrollPane = scrollPane;
}
@Override
public JPanel call() {
try {
BufferedImage image = ImageIO.read(url);
ImageIcon icon = new ImageIcon(setImage(image));
image.flush();
image = null;
jPanels[i] = new JPanel();
jPanels[i].setLayout(new BoxLayout(jPanels[i],
BoxLayout.Y_AXIS));
JLabel label = new JLabel();
label.setIcon(icon);
icon = null;
jPanels[i].add(label);
String name = "date";
if (name.length() > 35) {
name = name.substring(0, 32) + "...";
}
JLabel jLabel = new JLabel(name);
jPanels[i].add(jLabel);
scrollPane.add(jPanels[i]);
latch.countDown();
return jPanels[i];
} catch (Exception ex) {
ex.printStackTrace();
latch.countDown();
demo.infoBox("Failed to open file maybe file is open?",
"Error");
return new JPanel();
}
private static Image setImage(BufferedImage source) {
int height = 150;
int width = 150;
if (source.getHeight() / height > source.getWidth() / width) {
return source.getScaledInstance(source.getWidth() * height /
source.getHeight(), height, Image.SCALE_SMOOTH);
} else {
return source.getScaledInstance(width, source.getHeight() * width
/ source.getWidth(), Image.SCALE_SMOOTH);
}
}
答案 0 :(得分:0)
我认为getScaledInstance()
可能会保留其用于渲染该图像的缩放版本的原始图像的引用。
您应该尝试在setImage()
方法中执行的操作是创建一个新的BufferedImage
,并按比例缩小尺寸,然后使用此新createGraphics()
的{{1}}方法将缩放的实例绘制到这个新的BufferedImage
中。然后返回较小的新BufferedImage
而不是缩放后的实例本身。
此时,您应该有一个新的小图像,该图像不包含对原始大图像的任何引用,并且原始大图像将可以通过垃圾回收免费发布。
BufferedImage
答案 1 :(得分:0)
我只是用以下代码打开了图片,它解决了我的问题!
Toolkit工具箱= Toolkit.getDefaultToolkit(); 图片image = toolkit.getImage(url.getPath());