java堆内存问题

时间:2012-04-16 12:55:16

标签: java caching bufferedimage

我的申请基本上是photo browser。我的方法(不要评判我,我是java的新手)是让ArrayList填充BufferedImages,然后将图像添加到JList(左侧)。

这是我获取图片的方式:

private void getFullImage() {

        BufferedImage im = null;        


        ImageReader imageReader = null;
            try {
                System.out.println("Loading "+original+"...");
                String suffix = Utils.getFileExt(original.getName(), "jpg");
                @SuppressWarnings("rawtypes")
                Iterator readers = ImageIO.getImageReadersBySuffix(suffix);
                imageReader = (ImageReader)readers.next();
                imageReader.setInput(new FileImageInputStream(original));
                im = imageReader.read(0);
                imageReader.dispose();
            } catch (Exception e)
            {
                e.printStackTrace();
            }

        this.img = im;
    }

然后,在我获取所有数据后,我会将图像添加到JList

   Vector vector = new Vector();
   JPanel container = null;
   PhotoPanel pp = null;
   Photo p = null;
   for(int i=0;i<files.length;i++)
   {
        p = new Photo(files[i]);
        pp = new PhotoPanel(p);
        container = new JPanel(new BorderLayout());
        container.add(pp,BorderLayout.CENTER);
                                       container.setBorder(BorderFactory.createTitledBorder(p.getTitle()));
                                vector.addElement(container);
  }
   plist.setListData(vector);

如果我有10个文件,该应用程序运行良好。问题是我有更多的图像要显示。然后我会得到一个例外:Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space。所以,我知道我的方法非常糟糕,我想知道如何拍摄和存储所有图像并让它们显示在JList中。也许使用缓存?我读过有关SoftReference的内容,但我真的不知道如何使用它。感谢。

2 个答案:

答案 0 :(得分:5)

问题主要有两个可能的原因:


第一个,我发布的更多信息是警告,而不是实际原因,是因为System.out.println()在控制台上打印了过多的数据。

我不确定它是仅在NetBeans或所有开发工具中发生的。但不管怎样,它需要一个真正荒谬的打印量来触发它,我怀疑你有很多文件加载。

无论如何,如果您对System.out.println("Loading "+original+"...");行的意图是针对永久/生产日志记录,而不是为了开发/调试而暂时放置代码,那么最好使用Logger。 {1}}。您可以在this SO answer中阅读TL; DR版本的说明,您可以通过其中提供的链接进一步阅读,包括官方文档。


另一个原因,当然是您的原因,就是您同时加载了太多数据。解决方案是:

  1. 缩小图像(缩略图),仅显示所选图像的完整版本。请注意,这是一种快速的解决方案,并且不推荐!因为系统可能仍然承受不了太多。
  2. 仅在界面的可见部分出现图像(或所述图像的缩略图,以获得组合的最佳解决方案),并在界面导航时加载新图像(并卸载其他图像)。

答案 1 :(得分:0)

我在使用大型图像时遇到了很多困难(尽管在SWT中),而OutOfMemory和NoMoreHandles(如果没有足够的内存,甚至可能会发生)都是一场噩梦。我认为没有办法保留大图像或在内存中有大量图像。我同意Andrew的评论,但只是想补充一点,根据你的要求,你可以尝试扩展画布(或Swing中的任何内容)并直接在其上绘制你的图像,而不将其保存在内存中(类似于PaperClips#打印预览)。当然,你需要进行一些计算来正确布局图像,但我认为,在这种情况下,你可以克服你的内存问题(但是还会遇到其他一些问题:))