Java ImageIO删除图像后将不释放ram

时间:2019-08-23 07:54:09

标签: java image

我有一个程序,可以打开一些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);
        }
    }

2 个答案:

答案 0 :(得分:0)

我认为getScaledInstance()可能会保留其用于渲染该图像的缩放版本的原始图像的引用。

您应该尝试在setImage()方法中执行的操作是创建一个新的BufferedImage,并按比例缩小尺寸,然后使用此新createGraphics()的{​​{1}}方法将缩放的实例绘制到这个新的BufferedImage中。然后返回较小的新BufferedImage而不是缩放后的实例本身。

此时,您应该有一个新的小图像,该图像不包含对原始大图像的任何引用,并且原始大图像将可以通过垃圾回收免费发布。

BufferedImage

答案 1 :(得分:0)

我只是用以下代码打开了图片,它解决了我的问题!

Toolkit工具箱= Toolkit.getDefaultToolkit(); 图片image = toolkit.getImage(url.getPath());