多个SwingNode导致极端性能下降

时间:2015-11-27 00:44:24

标签: java swing javafx

当我在面板中有多个SwingNodes(JFXPanel中的GridPane)时,我注意到性能极端下降。如果只有一个SwingNode,则似乎不会发生这种情况。

我意识到在混合Swing和JavaFX时会出现一些预期的降级,但这会使应用程序几乎无法使用(我无法真正改变我的行业环境;遗留代码仍然在Swing中,但我们真的想要新的JavaFX图形实用程序)。

这是在Java 8u60上的Windows 7上运行。

MCVE:

import javax.swing.*;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;

public class SwingNodeTest {
    private static Scene createScene(JComponent button1, JComponent button2) {
        GridPane pane = new GridPane();
        pane.getColumnConstraints().add(new ColumnConstraints(100));
        pane.getColumnConstraints().add(new ColumnConstraints(200));

        SwingNode node1 = new SwingNode();
        // Best practice to call SwingNode->setContent(...) on the EDT, but doesn't make
        // a difference for the test.
        node1.setContent(button1);
        pane.add(node1, 0, 0);

        ToggleButton node2 = new ToggleButton("2");
        // Commenting out the above line and uncommenting the below lines cause EXTREME
        // Performance degradation.
//        SwingNode node2 = new SwingNode();
//        node2.setContent(button2);
        pane.add(node2, 1, 0);

        return new Scene(pane);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                JFXPanel panel = new JFXPanel();
                frame.setSize(800, 600);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(panel);
                frame.setVisible(true);

                JButton button1 = new JButton("1");
                JToggleButton button2 = new JToggleButton("2");

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        final Scene scene = createScene(button1, button2);
                        panel.setScene(scene);
                    }
                });
            }
        });
    }
}

编辑:在让MCVE运行几分钟后刚刚意识到,我得到OutOfMemoryErrors(超出GC开销限制)。

1 个答案:

答案 0 :(得分:1)

我将此提交为错误。截至撰写本文时,它目前已经打开并且在JDK积压中:

https://bugs.openjdk.java.net/browse/JDK-8144504

不幸的是,虽然这个bug是开放的,但唯一的解决办法似乎是将你的Swing限制为JavaFX到Swing集成。我们最终重新构建了JavaFX中JavaFX面板中使用的所有Swing小部件,这是一次相当大的改革。

对于任何在这里寻找解决方案的人来说,我也会发布这个JDK错误,在编写本文时也是如此:

https://bugs.openjdk.java.net/browse/JDK-8136530

该错误表明,即使您在JFXPanel中的JavaFX窗格中只有一个SwingNode,您的CPU使用率也会急剧增加(但不会发生冻结多个节点)。在我们认为通过限制JavaFX窗格中SwingNode实例的数量巧妙地解决了这个问题后,我们最终咬了咬我们。希望这个抬头将有助于防止其他人像我们一样进行面部种植。

编辑(2009年9月21日):冻结错误现已列为已修复的Java 10的修复版本.CPU使用量增加错误仍处于打开状态。