首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BufferdImage堆空间错误

BufferdImage堆空间错误
EN

Stack Overflow用户
提问于 2014-09-25 18:05:37
回答 1查看 1.1K关注 0票数 0

我正在开发一个基于Java桌面的应用程序。在这里,我的工作是将图像放入JLabel中。如果我将60个以上的图像加载到标签中,那么java会显示“堆空间错误”(见下文)。

我不想增加JDK的堆空间大小。我只想在JLabel中显示图像后释放内存。我对BufferedImage使用了flush():它不会清除内存。

以下是我的代码

代码语言:javascript
复制
public static void setImageInLabelFromBufferedImage(JLabel label, int commonWidth, int maxImageHeight, BufferedImage img) {
    try {

        if (img.getWidth() < commonWidth && img.getHeight() < maxImageHeight) {
            **img = Scalr.resize(img, Scalr.Mode.AUTOMATIC, img.getWidth(), img.getHeight(), Scalr.OP_ANTIALIAS);**
        } else {
            if (img.getWidth() > img.getHeight()) {
                if (img.getWidth() > commonWidth) {
                    img = Scalr.resize(img, Scalr.Mode.FIT_TO_WIDTH, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
                }
            } else if (img.getHeight() > img.getWidth()) {
                if (img.getHeight() > maxImageHeight) {
                    img = Scalr.resize(img, Scalr.Mode.FIT_TO_HEIGHT, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
                }
            } else {
                img = Scalr.resize(img, Scalr.Mode.FIT_EXACT, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
            }
        }

        //BufferedImage resizedImage = Scalr.resize(img, Scalr.Mode.AUTOMATIC, commonWidth, maxImageHeight, Scalr.OP_ANTIALIAS);
        label.setIcon(new ImageIcon(img));
        label.revalidate();
        img.flush();
        img = null;
        Runtime.getRuntime().gc();

    } catch (Exception e) {
        log.error("setImageInLabelFromBufferedImage==>" + e.getMessage());
    }

堆栈跟踪:

代码语言:javascript
复制
java.lang.OutOfMemoryError: Java heap space at 
java.awt.image.DataBufferByte.<init>(DataBufferByte.java:92) at 
java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:4‌​15) at 
java.awt.image.Raster.createWritableRaster(Raster.java:944) at 
javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:107‌​3) at 
javax.imageio.ImageReader.getDestination(ImageReader.java:2896) at 
com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:9‌​98) at 
com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:966)
EN

回答 1

Stack Overflow用户

发布于 2014-09-26 05:56:17

解码的图像数据(比JPG/PNG格式的压缩图像数据大得多)在显示时必须保存在某个地方,这个地方就是Heap。

如果你的意思是你想为不再显示的图像释放内存(例如,有人滚动过它们),你必须确保它们不能被paint调用渲染(例如,它们不在屏幕上),然后你不仅需要处理图像本身,还需要确保JLabel丢失对图像的引用,以便GC可以收集它- dispose只是一个清理图像使用的本机内存资源的提示,最终你需要BufferedImage资源本身GC‘,这意味着任何引用它的对象都需要删除它的引用。

这意味着您可能需要一个足够聪明的自定义组件,以便在滚动离开屏幕时清除图像引用,然后在它再次可见时重新加载它。

开箱即用的Swing不会为你做到这一点--你需要在这里发挥创意(我的意思是没有任何工作,它不会自动完成这项工作……您可能会使用componentListener并在可见性事件期间做一些创造性的事情)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26035839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档