如何检查FX应用程序的线程策略违规

4
我正在使用一个应用程序,其中大量使用了JavaFX。我注意到我们一直会收到类似于此 open jdk issue中提到的异常。这个问题提到了当您在 FX 应用程序线程外创建节点时,可能会发生异常。
我想找到任何访问 FX 对象的地方并将其放在 FX 线程之外,但应用程序太大了,无法通过检查来完成。我看到了一个类似的 Swing 问题和答案,但是没有找到类似于 JavaFX 的东西。那里最经常提到的 Swing 解决方案涉及自定义RepaintManager,它是一个针对 Swing 的特定接口。 因此如何(如果有必要)找出代码在FX应用程序线程以外的其他线程上访问JavaFX对象的位置,而不必手动检查所有应用程序的FX代码?
注意:我完全意识到在 FX 线程以外与 fx 对象交互是一个坏主意。一旦我发现策略违规行为,我也完全知道可以使用 Platform.runLater(()->{/*fx code*/}); 在 FX 线程上执行操作。我的问题是关于如何找到违规行为

Platform.runLater(new Runnable() { @Override public void run() { /* do stuff on the JFX thread */ } }); - SnakeDoc
@SnakeDoc:请看添加的注释。我知道如何在发现线程策略违规时修复它们。 - codeCogs
实际上,我认为你没有任何办法完成这个任务。 - jewelsea
你尝试过在分析器下查看应用程序的线程吗?它可以提供一些线索,告诉你哪个线程在何时做了什么。也许不完全是你寻找的答案,但这可能会有所帮助。JProfiler非常好用,但Oracle JDK(现在也许包括OpenJDK)内置了一个免费的分析器——JVisualVM。 - SnakeDoc
@SnakeDoc:我不确定如何最好地利用分析器来找到我要查找的信息。我想我可以定期强制线程转储,并查看是否有任何线程在FX堆栈中,但以这种方式捕获违规者的机会似乎是随意的(如果一个线程只在FX堆栈中花费1%的CPU时间呢?足以引起错误,但不太可能被快照捕获)。 - codeCogs
我自己没有尝试过,但也许FindBugs会指出一些问题? - SnakeDoc
1个回答

0

也许不是最理想的解决方案,但其中一个解决方法是在java.lang.ClassLoader.loadClass(String name,boolean resolve)中设置有条件的断点,并加上以下条件:

name.startsWith("javafx") && 
    !Thread.currentThread().getName().equals("JavaFX Application Thread")

每当从JavaFX包中加载新类时,您可以检查这些类是否在FX线程上加载。它肯定不会捕获所有违规行为,但是当一个线程使用导致加载尚未被使用的FX类的FX代码时,它将通过暂停违反线程来让您知道。

(如果可以将!javafx.application.Platform.isFxApplicationThread()添加到断点条件中,那就太好了,但是在Eclipse Luna中我遇到了一些问题。)

还要注意,并非每次触发此操作都是实际违规行为-可以加载类而不必实例化和/或与该类交互。例如,如果从非FX线程调用以下构造函数,则可能会触发断点,尽管并不危险:

public class MyClass{
    Label l = null; //Loading & instantiating MyClass loads
                    // the Label class, but doesn't necessarily
                    // violate the FX threading policy

    public MyClass(){

    }
}

这个解决方案总比没有好,但是(我已经发现了一个实际的违规行为)。


尝试使用FindBugs,我很想知道它是否能捕获此类问题(因为这可能相当常见)。 - SnakeDoc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接