当前位置: 首页 > 知识库问答 >
问题:

GTKLookAndFeel导致Ubuntu20死锁

公羊信厚
2023-03-14

我在运行以下代码时遇到了一个奇怪的问题:

public static void main(String[] args) throws Exception {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    JFrame frame = new JFrame("Test");
    frame.setLocationRelativeTo(null);
    SwingUtilities.invokeAndWait(JFXPanel::new);
    frame.add(new JFXPanel());
    Platform.runLater(() -> {
        JPanel panel = new JPanel();
        System.exit(0);
    });
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setSize(200, 100);
    frame.setVisible(true);
}

首先,代码是用OpenJDK-11和OpenJFX-11编译的,在Windows中运行良好(即退出System.exit(0)call)。

然而,如果我在Linux(特别是Ubuntu20.04)上运行这个程序,调用new JPanel()会锁定线程,程序永远不会退出。注释出UIManager。setLookAndFeel调用将使其重新正常工作。

我只是在com上遇到了一个bug。太阳JAVA摆动普拉夫。gtk。GTKLookAndFeel(这是SystemLookAndFeel返回的结果)或者我在这里做了什么错误/意外的事情?

共有1个答案

田曜瑞
2023-03-14

我在这里做错了什么/出人意料吗?

是的,您做错了:您违反了Swing线程策略,该策略规定

除非另有说明,否则必须在事件调度线程上访问所有Swing组件和相关类。

main方法中的大部分代码都应该在AWT事件调度线程上执行。您可以通过使用SwingUtilities来实现这一点。调用器(…)

例外情况如下:

>

  • 平台。runLater(…) ,它计划在FX应用程序线程上运行一些东西,它本身可以从任何地方调用。但是,您在其中调用的new JPanel()不应该在FX应用程序线程上执行,而应该在AWT事件调度线程上执行。

    SwingUtilities。调用EANDWAIT(…) 。这会安排要在AWT事件调度线程上执行的代码,并暂停当前线程,直到完成。因此调用SwingUtilities。调用EANDWAIT(…)将导致死锁。密码

     SwingUtilities.invokeAndWait(JFXPanel::new);
    

    调度要在AWT事件调度线程上执行的new JFXPanel(),并阻止当前线程,直到完成。如果您已经在AWT事件调度线程上,只需调用

     new JFXPanel();
    

    实现了同样的目标。

    我知道你的代码试图创建一个最小的可复制示例,但它并不清楚它是什么示例,因为其中有一些代码的目的完全不清楚。例如,创建两个JFXPanel实例,第一个实例被丢弃。然后你创建了一个JPanel,你同样会在错误的线程上故意丢弃它。

    我没有Linux环境来测试这一点,但您发布的最接近“正确”版本的代码如下:

    public static void main(String[] args) throws Exception {
    
        // We are not on the AWT event dispatch thread, so if we
        // want to create and access Swing components, we must wrap
        // that code inside SwingUtilities.invokeLater(...):
    
        SwingUtilities.invokeLater(() -> {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            JFrame frame = new JFrame("Test");
            frame.setLocationRelativeTo(null);
    
            // We must not call SwingUtilities.invokeAndWait(...)
            // from the event dispatch thread, so remove this:
            // SwingUtilities.invokeAndWait(JFXPanel::new);
    
            // To create new JFXPanel and block until the call is
            // complete, we just create it in the usual way (since
            // we're already on the event dispatch thread)
            new JFXPanel();
    
            frame.add(new JFXPanel());
            Platform.runLater(() -> {
                // This code block is executed on the FX Application Thread
                // To create a swing component, we must wrap the
                // code in SwingUtilities.invokeLater(...), so it's
                // executed on the Event Dispatch Thread:
                SwingUtilities.invokeLater(() -> {
                    JPanel panel = new JPanel();
                    System.exit(0);
                });
            });
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frame.setSize(200, 100);
            frame.setVisible(true);
        });
    
    }
    

    另外,请注意,看起来和感觉只会影响Swing组件;它不会影响JavaFX控件,其外观和行为由JavaFX管理(默认情况下由默认的CSS样式表管理)。因此,您放在JFXPanel中的任何内容都不会受到看起来和感觉的影响。

  •  类似资料:
    • seata版本:1.4.0,但1.4以下的所有版本也都有这个问题 问题描述:在一个全局事务中,一个分支事务上的纯查询操作突然卡住了,没有任何反馈(日志/异常),直到消费端RPC超时 问题排查 整个流程在一个全局事务中,消费者和提供者可以看成是全局事务中的两个分支事务,消费者 --> 提供者 消费者先执行本地的一些逻辑,然后向提供者发送RPC请求,确定消费者发出了请求已经并且提供者接到了请求 提供者

    • 在使用信号量时,我应该注意多线程问题吗?在我的测试之后,似乎有一段时间信号灯#release not cause acquire wake up,即使有足够的许可证。 底部是我的测试代码。 带有2个许可证的信号灯 Thread3和Thread2先向上 线程3获取许可,等待锁,锁将由线程1通知 线程2获取许可,等待锁1,锁1将由线程3通知 线程1启动,线程1和线程2先睡眠30ms启动 线程1通知锁定

    • 我遇到了一些使用c#的/关键字进行异步编程的最佳实践(我是c# 5.0的新手)。 给出的建议之一如下: 稳定性:了解您的同步上下文 ...一些同步上下文是不可重入的和单线程的。这意味着在给定时间只能在上下文中执行一个工作单元。这方面的一个例子是Windows UI线程或ASP.NET请求上下文。在这些单线程同步上下文中,很容易死锁。如果您从单线程上下文中生成一个任务,然后在上下文中等待该任务,您的

    • 问题内容: 与多个用户一起测试我的应用程序时,我遇到了ORA-00060死锁错误。我不确定如何确定此错误的原因,因此,如果有人可以帮助我,将不胜感激。 我查看了为此事件生成的跟踪文件,它显示了导致此问题的查询: 它也产生了这个: 我如何使用以上信息来找出导致问题的原因?TABLE_A或TABLE_B上都没有任何未索引的外键(我相信这通常是导致这种类型错误的原因)。 当我运行此查询时: 我在完全不同

    • 请问上述代码的第70行换成第71行注释的内容时,为什么会造成死循环。 题目: https://www.acwing.com/problem/content/174/

    • 我试图使用C++11的std::condition_variable,但是当我试图从第二个线程锁定与其关联的unique_lock时,我得到一个异常“资源死锁已避免”。创建它的线程可以锁定和解锁它,但不能锁定第二个线程,即使我非常肯定unique_lock不应该在第二个线程试图锁定它的地方已经锁定。 FWIW我在Linux中使用gcc4.8.1和-std=gnu++11。 我已经围绕conditi