簡體   English   中英

Java ImageIO刪除圖像后將不釋放ram

[英]Java ImageIO won't free ram after deleting 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);
        }
    }

我認為getScaledInstance()可能會保留對原始圖像的引用,該圖像用於呈現該圖像的縮放版本。

您應該在setImage()方法中嘗試做的是創建一個具有所需縮小比例的新BufferedImage ,然后使用此新BufferedImagecreateGraphics()方法將縮放后的實例繪制到此新BufferedImage 然后返回新的,較小的BufferedImage而不是縮放后的實例本身。

此時,您應該有一個新的小圖像,該圖像不包含對原始大圖像的任何引用,並且原始大圖像將可以由垃圾回收自由釋放。

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

我只是用下面的代碼打開圖像,它解決了我的問題!

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM