【问题标题】:JavaFX OutOfMemoryError with animated GIFs带有动画 GIF 的 JavaFX OutOfMemoryError
【发布时间】:2013-12-17 08:00:21
【问题描述】:

我正在创建一个具有图像浏览器的 JavaFX 2.0 应用程序,当我在浏览多个 GIF 之后遇到一些 OutOfMemoryError 异常时,它应该能够显示动画 GIF。我设法将相关代码隔离到“GifCrasher”应用程序中:

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;

import javafx.scene.image.Image;


public class GifCrash {

    // Settings:
    private static  long            waitTime    =   100;    // msec
    private static  ArrayList<File> imageFiles  =   new ArrayList<File>() {{
                                                    add(new File("thrillercat.gif"));
                                                }};

    // Other:
    private static  long    totalSize   =   0;
    private static  long    gifsLoaded  =   0;

    public static void main(String[] args) throws Exception {

        while(!Thread.currentThread().isInterrupted()) {
            // Read gif file:
            File        imageFile   =   GifCrash.imageFiles.get((int) (GifCrash.gifsLoaded % GifCrash.imageFiles.size()));
            InputStream iStream     =   new FileInputStream(imageFile);
            Image       image       =   new Image(iStream);
            iStream.close();

            // Display info:
            GifCrash.gifsLoaded++;
            GifCrash.totalSize += imageFile.length();
            System.out.println("Loaded " + imageFile + " (" + imageFile.length() + " bytes)");
            System.out.println("GifCount\t=\t" + GifCrash.gifsLoaded);
            System.out.println("TotalSize\t=\t" + Math.round((double) GifCrash.totalSize / (1024 * 1024)) + " MBytes (" + GifCrash.totalSize + " bytes)");
            System.out.println();

            // Wait?
            if (GifCrash.waitTime > 0) {
                Thread.sleep(GifCrash.waitTime);
            }
        }
    }
}

这个简单的应用程序构建 javafx Image 对象而不实际对它们做任何事情,因此据我所知,这些对象应该被垃圾收集。在示例应用程序中,我通过每次重新加载相同的 GIF 来模拟加载多个不同的 GIF,而不是将其缓存在某个地方(这样我就不必找到超过 250MBytes 的 GIF 文件)。我还添加了一个可选的waitTime 参数以确保垃圾收集器有机会释放一些内存。但是,使用imageFiles 中的动画 GIF 文件运行此应用程序在一段时间后仍会产生 OutOfMemoryError(在我的情况下,在加载大约 250MBytes 的动画 GIF 之后)。使用 PNG 文件运行应用程序完全没有问题,似乎动画 GIF 是唯一的问题。

这些是我用于测试的图像:thrillercat.gifcatdestroyer.png。 这是我在运行应用程序时得到的(截断的)输出。

Loaded thrillercat.gif (1203120 bytes)
GifCount    =   1
TotalSize   =   1 MBytes (1203120 bytes)

Loaded thrillercat.gif (1203120 bytes)
GifCount    =   2
TotalSize   =   2 MBytes (2406240 bytes)

...

Loaded thrillercat.gif (1203120 bytes)
GifCount    =   225
TotalSize   =   258 MBytes (270702000 bytes)

Loaded thrillercat.gif (1203120 bytes)
GifCount    =   226
TotalSize   =   259 MBytes (271905120 bytes)

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.sun.javafx.iio.gif.GIFImageLoader2.decodePalette(GIFImageLoader2.java:288)
    at com.sun.javafx.iio.gif.GIFImageLoader2.load(GIFImageLoader2.java:191)
    at com.sun.javafx.iio.ImageStorage.loadAll(ImageStorage.java:294)
    at com.sun.javafx.iio.ImageStorage.loadAll(ImageStorage.java:244)
    at com.sun.javafx.tk.quantum.PrismImageLoader2.loadAll(PrismImageLoader2.java:107)
    at com.sun.javafx.tk.quantum.PrismImageLoader2.<init>(PrismImageLoader2.java:41)
    at com.sun.javafx.tk.quantum.QuantumToolkit.loadImage(QuantumToolkit.java:607)
    at javafx.scene.image.Image.loadImage(Image.java:942)
    at javafx.scene.image.Image.initialize(Image.java:722)
    at javafx.scene.image.Image.<init>(Image.java:625)
    at GifCrash.main(GifCrash.java:27)

一如既往,我认为这是由于我的代码中的一些错误而不是错误,那么我在这里做错了什么?

如果这是一个错误,有没有办法解决它?即,我需要能够在 JavaFX 窗口中显示大量动画 GIF(一次只能看到一个 GIF)。

谢谢!

【问题讨论】:

    标签: java javafx-2 out-of-memory animated-gif


    【解决方案1】:

    只需使用Java 8,您的示例程序适用于 Java 8 版本。

    我在 Java 7u45 (OS X 10.8) (MacBook Air 2012, 4gb ram) 上尝试了示例程序,但在 71 次迭代后它始终耗尽内存。

    而在 Java 8 中,程序在运行 5000 次迭代后从未耗尽内存:

    Loaded /Users/lilyshard/dev/playfx/src/thriller-cat-o.gif (1203120 bytes)
    GifCount    =   10000
    TotalSize   =   11474 MBytes (12031200000 bytes)
    

    我没有让您的程序在 Java 7u45 上运行的解决方法,并且在 Java 8 分支上进行的错误修复不太可能向后移植到 JavaFX 2.2。有时,错误修复会根据用户请求通过 JavaFX 问题跟踪器进行反向移植,但这种情况很少发生。

    我的猜测是 JavaFX 2.2 gif 加载器中的一些错误已经修复,为 Java 8 版本做准备。

    【讨论】:

    • 感谢您的回答!嗯,很遗憾,我就等到Java8成为当前版本吧。
    猜你喜欢
    • 2013-12-22
    • 2016-08-23
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2021-03-19
    • 2015-03-26
    相关资源
    最近更新 更多