简体   繁体   English

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

[英]Java ImageIO won't free ram after deleting image

I have a program that opens some 8k images and resizes them to 200x200 pixels. 我有一个程序,可以打开一些8k图像并将其大小调整为200x200像素。 The program works fine but the problem is it won't free memory after closing each image so it runs out off memory super fast! 该程序运行良好,但问题是关闭每个图像后它不会释放内存,因此它会很快耗尽内存! (after like 40 images) (之后喜欢40张图片)

I have tried flushing and setting image to null, using system.gc(), Also I can't use ImageReader because images aren't formatted properly and says not a jpeg image start with 0x01 0x11 and some other numbers. 我尝试使用system.gc()刷新并将图像设置为null,而且我不能使用ImageReader,因为图像格式不正确,并且说jpeg图像不是以0x01 0x11开头以及其他一些数字。 Also enabling disabling ImageIO.usecatch won't help. 同时启用禁用ImageIO.usecatch也无济于事。 I tried to use a global variable for image but it didn't help too. 我尝试对图像使用全局变量,但它也无济于事。

I need to run program in threads but it uses too much memory even on a single thread after editing some images. 我需要在线程中运行程序,但是在编辑一些图像后,即使在单个线程上,它也会占用过多的内存。 I removed extra parts of code that i confirmed have nothing to do with problem. 我删除了我确认与问题无关的多余代码部分。

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);
        }
    }

I think it's likely that getScaledInstance() keeps a reference to the original image that it uses to render the scaled version of that image. 我认为getScaledInstance()可能会保留对原始图像的引用,该图像用于呈现该图像的缩放版本。

What you should try doing in your setImage() method is creating a new BufferedImage of the desired scaled-down dimensions, then using the createGraphics() method of this new BufferedImage to draw the scaled instance into this new BufferedImage . 您应该在setImage()方法中尝试做的是创建一个具有所需缩小比例的新BufferedImage ,然后使用此新BufferedImagecreateGraphics()方法将缩放后的实例绘制到此新BufferedImage Then return the new, smaller BufferedImage rather than the scaled instance itself. 然后返回新的,较小的BufferedImage而不是缩放后的实例本身。

You should at that point have a new small image that's free of any references to the original large image, and the original large image will be free to be released by garbage collection. 此时,您应该有一个新的小图像,该图像不包含对原始大图像的任何引用,并且原始大图像将可以由垃圾回收自由释放。

private static Image setImage(BufferedImage source) {
    int height = 150;
    int width = 150;
    Image scaledImage;

    if (source.getHeight() / height > source.getWidth() / width) {
        width = source.getWidth() * height / source.getHeight();
        scaledImage = source.getScaledInstance(width, height, Image.SCALE_SMOOTH);
    } else {
        height = source.getHeight() * width / source.getWidth();
        scaledImage = source.getScaledInstance(width, height, Image.SCALE_SMOOTH);
    }

    BufferedImage result = new BufferedImage(widht, height, BufferedImage.TYPE_INT_RGB);
    result.createGraphics().drawImage(scaledImage, new AffineTransform(), null);

    return result;
}

I simply opened image with following code and it fixed my problem! 我只是用下面的代码打开图像,它解决了我的问题!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM