【问题标题】:java heap memory issuejava堆内存问题
【发布时间】:2012-04-27 19:18:12
【问题描述】:

我的申请基本上是photo browser。我的方法(不要评判我,我是 java 新手)是用 BufferedImages 填充 ArrayList,然后将图像添加到 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 的东西,但我真的不知道如何使用它。谢谢。

【问题讨论】:

  • @Andrew 会突破界限,但仍然不适用于任意数量的照片。
  • @Jakub 我认为@TheLima 搞定了。噪音已删除。

标签: java caching bufferedimage


【解决方案1】:

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


首先,在您的情况下,我发布的更多是警告而不是实际原因,是使用System.out.println() 在控制台上打印了过多的数据。

我不确定它是否只发生在 NetBeans 或所有开发工具中。但无论哪种方式,它都需要大量的打印才能触发,而且我怀疑你加载了那么多文件。

无论如何,如果您使用 System.out.println("Loading "+original+"..."); 行的意图是用于永久/生产日志记录,而不是您出于开发/调试目的而临时添加代码,那么您最好使用适当的 Logger .您可以在this SO answer 中阅读 TL;DR 版本的说明,还可以通过那里提供的链接进一步阅读,包括官方文档。


另一个原因,这很肯定是您的原因,是您同时加载了太多数据。解决方案是:

  1. 缩小图像(制作缩略图),仅显示所选图像的全尺寸版本。请注意,这是一种快速的解决方法,不推荐使用!因为系统可能仍然无法承受。
  2. 仅加载界面可见部分的图像(或所述图像的缩略图,以获得最佳的组合解决方案),并在导航界面时加载新图像(并卸载其他图像)。李>

【讨论】:

  • 您可以通过增加分配给应用程序的堆空间来使用第一种技术“进一步推动边界”,但第二种方法要好得多。 +1
  • 好的,我该如何采用第二种方法?
  • 当用户滚动浏览可用图像时,放下一张图像并添加另一张。或者加载 x 个图像并仅显示 x-2 个,当用户滚动浏览时,再加载一个,因为您显示已加载但未显示的图像之一。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2020-02-02
    • 2011-11-26
    • 2021-04-19
    • 2016-02-12
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2019-07-04
    • 2018-03-11
    相关资源
    最近更新 更多