当我加载大约11k个40mb大小的图像时,为什么会出现java堆空间异常



我的程序中有一种情况,我需要访问保存在硬盘上的一定数量的图像。我要么只在真正需要的时候加载它们,要么在启动时就已经全部加载了。

出于好奇,我试图从几个文件夹中读取所有(约11k)图像,并将其保存在几个列表中。我想知道这是否需要太长时间,但在阅读了大约9k张图像后,收到了OutOfMemoryError。

我的JRE的堆大小为1g(-Xmx1g)。

为什么我的代码会出现这种情况?我是在制造内存泄漏吗?你对不再经历这种情况有什么建议吗?或者解决方案是在我需要时只读取文件吗?所有文件的总大小只有40mb左右,所以我认为把它保存在内存中是可以的(40mb似乎与我的1g堆大小相比不算太多)。或者java在加载后会执行一些疯狂的魔术,将文件大小乘以高数字?

我对stackoverflow做了一些研究,但无法真正将给定的答案(比如从这里或这里)转化为我的案例。所以,如果你们中有人有想法,我会非常高兴:)

我的代码在这里,如果有点难看的话,很抱歉——我只是在乱搞:

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
public class FatfontsManager {
    private List<BufferedImage> until9;
    private List<BufferedImage> until99;
    private List<BufferedImage> until999;
    private List<BufferedImage> until9999;
    // loads and keeps all images 
    public FatfontsManager() {
        until9 = new ArrayList<>();
        until99 = new ArrayList<>();
        until999 = new ArrayList<>();
        until9999 = new ArrayList<>();
        String absolutPathToThisProject = new java.io.File("")
                .getAbsolutePath();
        // load Images
        for (int i = 1; i < 10; i++) {
            until9.add(loadImage(absolutPathToThisProject
                    + "\latexDir\0..9\" + i + ".png"));
        }
        System.out.println("1 - 9 loaded");
        for (int i = 1; i < 100; i++) {
            until99.add(loadImage(absolutPathToThisProject
                    + "\latexDir\0..99\" + i + ".png"));
        }
        System.out.println("1 - 99 loaded");
        for (int i = 1; i < 1000; i++) {
            until999.add(loadImage(absolutPathToThisProject
                    + "\latexDir\0..999\" + i + ".png"));
        }
        System.out.println("1 - 999 loaded");
        for (int i = 1; i < 10000; i++) {
            until9999.add(loadImage(absolutPathToThisProject
                    + "\latexDir\0..9999\" + i + ".png"));
        }
        System.out.println("1 - 9999 loaded");
    }
    public static void main(String[] args) {
        new FatfontsManager();
    }
    public static BufferedImage loadImage(String ref) {
        BufferedImage bimg = null;
        try {
            bimg = ImageIO.read(new File(ref));
        } catch (Exception e) {
            System.err.println("Error loading image file " + ref);
            e.printStackTrace();
        }
        return bimg;
    }
}

非常感谢你的每一个回答。

所有文件的总大小仅为40mb左右。。。

但是,当您将图像文件加载到内存中时,图像将被解压缩并转换为像素阵列。根据原始图像文件格式(和压缩参数),这可能需要数量级或更多的堆空间。

目前还不完全清楚你想要实现什么,但也许你应该考虑只在实际使用这些图像时将其缓存在内存中。

最新更新