触发事件时自发的NullPointerExceptions

Spo*_*ing 15 java lambda multithreading javafx exception

我目前正在与LWJGL库结合使用JavaFX Level Editor,以实现OpenGL功能,从而使用多线程.

然而,我的问题是,有时当我触发JavaFX事件时(当我按下按钮/键等时),我得到了这种自发性java.lang.NullPointerException.我似乎无法弄清楚何时发生错误的模式,并且由于一些奇怪的原因,堆栈跟踪不会向我提供异常发生的位置.我所知道的是,当我以某种方式与JavaFX应用程序线程交互时,就会发生这种情况.

但是当它确实发生时,它不仅会将其打印到控制台一次然后崩溃.发生的情况是应用程序不断地反复打印出错误消息,直到我强行关闭应用程序.发生错误时,我似乎无法再触发某些特定事件.

这是我得到的自发重复错误消息:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.Scene$ScenePulseListener.synchronizeSceneNodes(Unknown Source)
at javafx.scene.Scene$ScenePulseListener.pulse(Unknown Source)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Unknown Source)
at com.sun.javafx.tk.Toolkit$$Lambda$153/452428720.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Unknown Source)
at com.sun.javafx.tk.Toolkit.firePulse(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$400(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$42/424424770.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/12064136.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

我猜这与"同步节点"有关.由于我正在使用多线程来运行OpenGL渲染循环,这可能与案例有关.我也在使用Java8中的Lambda Expression,显然正如它在错误日志中所说的那样,它也与它们有关.

我不希望有人给我一个确切的答案,我的问题是什么,以及我做错了什么,因为我没有提供任何代码(因为我的项目太大而且我不知道Exception发生在哪里).但是,我有一些通用的问题:

  1. 这个错误日志是什么意思?

  2. 什么可能导致这个?

  3. 为什么它没有向我提供有关异常发生地点的任何信息?

我设法通过将Eclipse中的JRE从JRE安装切换到JDK提供的jar来从堆栈跟踪中获取行号.这允许我从编译的API中获取行号,例如JavaFX本身.

这是新的错误日志:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.Scene$ScenePulseListener.synchronizeSceneNodes(Scene.java:2289)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2419)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:314)
at com.sun.javafx.tk.Toolkit$$Lambda$153/478814140.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:313)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:340)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:525)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:505)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$400(QuantumToolkit.java:334)
at com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$42/1940618951.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$38/640174177.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

我的错误在于JavaFX类,可能在我的lambda表达式中的某个地方,因为它仍然说的唯一地方(未知来源)也是"lambda".也许堆栈跟踪无法在lambdas中显示行号?

无论如何,这是返回NullPointerException的代码行:

if (node.getScene() == Scene.this)
Run Code Online (Sandbox Code Playgroud)

这是在JavaFX Scene类中

Rek*_*kin 2

不是答案,只是对一个非常相似的问题(Swing 问题)进行故障排除的建议。

为了避免任何猜测,我们应该查看源代码 - 解决“未知来源”部分。您提供的堆栈跟踪缺少行号。这是因为,标准 JRE 是在没有任何调试信息的情况下编译的。我相信在 Sun 时代,人们可以下载一个针对开发人员的单独发行版,其中包含所有调试符号。除了获得准确的行号之外,还可以在 JDK 代码中设置断点。

我们可以从那里开始调查问题。

如果没有带有调试符号的 JRE,您可以随时尝试编译自己的 JRE!我曾经成功编译过 JDK 发行版附带的“src.zip”文件。但它不是独立的!缺少几个部分,一些 Linux 特定的类等。JDK 本身的 javac 文件存在问题 - 它总是内存不足。幸运的是,Eclipse 的 javac 编译器可以处理大型代码库并部分编译类。

然后,我在引导类路径中使用生成的 jar(使用调试符号编译的 src.zip)运行我的程序。通常,您不允许修改“java. ”和“sun. ”包内的任何内容。使用引导类路径,您可以。

现在,回到您的特定问题:JavaFX 和 OpenGL 都通过所谓的“线程限制”解决多线程问题。这意味着,一切都是强制单线程的。您的问题可能是由于 javaFx 和 OpenGL 都有各自独立的线程这一事实引起的!我敢打赌,您在 JavaFX 的 EDT 之外进行了一些交互。但这只是一个牵强的假设。尝试获取源代码行,我们可以从那里继续。

当我需要调试信息时,我正在遵循这里的答案:debug jdk source can't watch Variable What it is

但是,所有的工作可能都不需要!我刚刚了解到,您可以将源文件本身附加到启动类路径,如下所示: https: //stackoverflow.com/a/10498425


更新,

所以,似乎“节点”引用为空(我怀疑“这个”为空)。下一步将识别空节点并找到添加它的确切时间。我可能会在程序中所有合理的“addNode”调用处放置一些断点(或打印输出语句)。

从源代码(我快速浏览了http://grepcode.com/file/repo1.maven.org/maven2/net.java.openjfx.backport/openjfx-78-backport/1.8.0-ea-b96.1 /javafx/scene/Scene.java#2263)看来,“null”引用来自“dirtyNodes”数组”。

我最好的选择通常是,您间接调用 addToDirtyNodes (http://grepcode.com/file/repo1.maven.org/maven2/net.java.openjfx.backport/openjfx-78-backport/1.8 .0-ea-b96.1/javafx/scene/Scene.java#503)来自正确线程之外。令我惊讶的是,第一行检查它是否是从正确的行调用的:

Toolkit.getToolkit().checkFxUserThread();

您是否碰巧在程序的输出中看到“Not on FX application thread; currentThread =”行?

我们只是希望,这不是 JavaFX 本身的错误。