【问题标题】:Bizarre JavaFX8 OutOfMemoryError - FadeTransition奇怪的 JavaFX8 OutOfMemoryError - FadeTransition
【发布时间】:2014-12-02 13:45:12
【问题描述】:

在我的应用程序中尝试追踪内存错误数小时后,我设法在一个简单的 JFX 程序中将其减少为一些非常奇怪的行为:

举个简单的例子,将一个矩形逐渐淡化到透明的画布上:

public class Test extends Application {

    @Override
    public void start(Stage primaryStage) {
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        int width = 1920;
        int height = 1080;

        Rectangle rect = new Rectangle(width, height);
        rect.setFill(Color.SALMON);
        rect.setOpacity(0);
        StackPane scenePane = new StackPane();
        scenePane.getChildren().add(rect);
        primaryStage.setScene(new Scene(scenePane));
        primaryStage.setWidth(width);
        primaryStage.setHeight(height);
        primaryStage.show();
        FadeTransition ft = new FadeTransition(Duration.millis(10000), rect);
        ft.setToValue(1);
        ft.play();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

当使用 VM args -Xms100m -Xmx100m 运行时,这完全没有问题。但是,当我为虚拟机提供大量更多内存(例如-Xms1000m -Xmx1000m)时,它很快就会崩溃:

java.lang.OutOfMemoryError
        at sun.misc.Unsafe.allocateMemory(Native Method)
        at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:127)
        at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
        at com.sun.prism.impl.BufferUtil.newByteBuffer(BufferUtil.java:90)
        at com.sun.prism.impl.BufferUtil.newIntBuffer(BufferUtil.java:121)
        at com.sun.javafx.tk.quantum.UploadingPainter.run(UploadingPainter.java:148)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
        at java.lang.Thread.run(Thread.java:745)

我尝试过的不止一个分析器显示堆几乎不占用任何分配的空间 - 但任务管理器中的进程视图显示它在几秒钟内通过所有可用内存。

然而,奇怪的事情并没有就此结束——它似乎只在 widthheight 的某些值(例如 1921 年的 width 意味着应用程序执行良好,看不到错误)。 )

这似乎只发生在透明阶段。如果没有在第一行的舞台上设置透明样式,一切似乎都很好(无论如何我都尝试过所有配置。)同样,它只发生在 Java 8 上(我使用的是 8u20)——Java 7 一切都很好/JFX 2.x。我正在运行 Windows 7x64。

任何人都可以重现此问题,并且任何人都可以阐明到底发生了什么?!这是迄今为止我遇到的最奇怪的事情......

更新:我已经设法在单独的 Windows 8 机器上重现了这个,但是另一个 Windows 7 机器(和 Mac)看起来都很好。不确定我正在使用什么 JFX 代码路径,但不幸的是,它似乎完全依赖于机器。

【问题讨论】:

  • 如果您在新的Thread 中调用ft.play();,问题会消失吗?
  • @ElliottFrisch 不,只是尝试了相同的结果。

标签: java memory-leaks javafx javafx-8 fade


【解决方案1】:

这只能回答你的部分问题,但这就是为什么增加你的堆会导致OutOfMemeoryError

从堆栈跟踪中可以看出,JavaFX 使用DirectByteBuffer 进行处理 - 因此数据存储在堆中,而是存储在本机内存中。通过增加(固定)堆大小,您可以减少操作系统可以作为本机内存提供的可用内存量。

例如在使用 32 位 Java-VM 的 Windows 上,可寻址内存范围为 4GB,为操作系统保留 2GB,为 java 应用程序保留 2GB。使用-Xms1000m -Xmx1000m 时,另外一个 GB 被保留用于堆,剩下 1 GB 用于 VM 代码、堆栈、非堆内存(如 PermGen 等),而最后剩下的 GB 可以用作本机内存。

【讨论】:

  • +1 和好点 - 我没有考虑到这一点。不过,正如您所说,我认为这不是全部问题,因为我可以将堆大小降低到 900m 或高达 1500m,但仍然存在问题。 (我不希望淡入淡出过渡的本机内存使用量接近 600m 标记。)
  • 我也不认为这是一个使用 600m 的过渡,但您还应该注意操作系统级别的内存消耗 - 例如使用任务管理器。
  • 我有 - 一旦过渡开始,它就会飙升到大约 1500m,然后内存不足。 FWIW,我提交了一个 JIRA:javafx-jira.kenai.com/browse/RT-38923 - JFX 家伙似乎认为这是因为 GC 在释放本机堆方面不够积极,因为它们必须排队,这是有道理的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多