Подтвердить что ты не робот

Спонтанные NullPointerExceptions при запуске событий

В настоящее время я создаю редактор уровней JavaFX в сочетании с библиотекой LWJGL для реализации возможностей OpenGL и, таким образом, используя многопоточность.

Моя проблема, однако, в том, что иногда, когда я запускаю события JavaFX (когда я нажимаю кнопку/клавишу и т.д.), я получаю этот спонтанный java.lang.NullPointerException. Я не могу понять, как именно происходит ошибка, и по какой-то странной причине stacktrace не предоставит мне, где произошло исключение. Все, что я знаю, это то, что это происходит, когда я каким-то образом взаимодействую с JavaFX Application Thread.

Однако, когда это происходит, он не только печатает его на консоли один раз, а затем падает. Случается, что приложение непрерывно выводит сообщение об ошибке снова и снова, пока я не закрою приложение. Похоже, я больше не могу запускать некоторые определенные события, когда произошла ошибка.

Это спонтанное повторяющееся сообщение об ошибке, которое я получаю:

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)

Я предполагаю, что это имеет какое-то отношение к "синхронизирующим узлам". Поскольку я работаю с многопотоковой обработкой для запуска цикла рендеринга с OpenGL, это может иметь какое-то отношение к делу. Я также использую выражение Lambda Expression из Java8, и, по-видимому, как он говорит в журнале ошибок, это тоже имеет отношение к ним.

Я не ожидаю, что кто-то даст мне точный ответ на мою проблему, и то, что я сделал неправильно, поскольку я не предоставляю никакого кода (потому что мой проект слишком велик, и я не знаю, где Исключение имеет место). Однако у меня есть несколько общих вопросов:

  • Что означает этот журнал ошибок?

  • Что может быть причиной этого?

  • Почему это не дает мне никакой информации о том, где произошло исключение?

Мне удалось получить номера строк из stacktrace, переключив JRE в Eclipse с установки JRE на банку, предоставленную JDK. Это позволило мне получить номера строк из скомпилированных 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)

Моя ошибка лежит в классах JavaFX и, вероятно, где-то внутри моего выражения лямбда, так как единственное место, где он все еще говорит (Неизвестный источник), там, где он также говорит "лямбда". Может быть, stacktrace не может отображать номера строк в lambdas?

В любом случае, это строка кода, которая возвращает исключение NullPointerException:

if (node.getScene() == Scene.this)

Это в классе класса JavaFX

4b9b3361

Ответ 1

Не ответ, только предложение от устранения неполадок очень похожей проблемы - Swing.

Чтобы избежать каких-либо догадок, мы должны посмотреть исходный код - разрешить часть "неизвестный источник". В стеке, которое вы указали, не хватает номеров строк. Это связано с тем, что стандартная JRE скомпилирована без какой-либо отладочной информации. Однажды я верю, что во времена Солнца можно было скачать отдельный дистрибутив, предназначенный для разработчиков со всеми отладочными символами. Это позволило, помимо наличия точных номеров строк, также установить контрольные точки внутри кода JDK.

Мы могли бы начать расследование вопросов прямо оттуда.

Если нет JRE с символами отладки, вы всегда можете попробовать составить свой собственный! Я когда-то успешно скомпилировал файл "src.zip", который сопровождал дистрибутив JDK. Однако это было не самодостаточно! Не хватало нескольких частей, некоторые классы Linux и т.д. У javac от JDK были проблемы с файлом - все время работало из памяти. К счастью, компилятор Eclipse javac может работать с большой базой кода и частично компилировать классы.

Затем я запустил мою программу с полученным банком (src.zip, скомпилированным с символами отладки) в пути к bootstrap. Обычно вам запрещено изменять что-либо внутри "java". и "солнце". пакеты. С помощью bootstrap classpath вы можете.

Теперь вернемся к вашей определенной проблеме: и JavaFX, и OpenGL решают проблемы многопоточности, так называемым "ограничение потока". Это означает, что все сильно однопоточно. Вероятно, ваши проблемы возникают из-за того, что оба javaFx и OpenGL имеют свои отдельные потоки! Я уверен, что вы сделали какое-то взаимодействие вне JavaFX EDT. Но это только далекая гипотеза. Попытайтесь получить исходные строки, мы могли бы продолжить оттуда.

В то время, когда мне нужна была информация об отладке, я отвечал следующим ответом: Отладочный источник jdk не может просматривать переменную, что она есть

Но вся работа может не понадобиться! Я только что узнал, вы могли бы прикрепить исходные файлы к пути к загрузке, как указано здесь: fooobar.com/questions/415165/...


Update

Итак, кажется, что ссылка "node" равна null (я сомневаюсь, что "this" имеет значение null). Следующий шаг будет определять нулевое значение node и найти точное время его добавления. Я бы, вероятно, поставил некоторые точки останова (или заявления распечатки) во всех разумных вызовах 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) извне соответствующего Thread. К моему удивлению, есть первая строка, которая проверяет, вызвала ли она ее из правильной:

Toolkit.getToolkit() checkFxUserThread();.

Вам не удалось увидеть строку "Не на потоке приложения FX, currentThread =" на выходе вашей программы?

Надеюсь, это не ошибка в самом JavaFX.

Ответ 2

Не не изменяйте свой графический интерфейс в потоке, отличном от GUI.

Поскольку я не вижу ваш код, я не уверен, где именно вы это делаете, но у меня была такая же проблема, и оказалось, что я передал объект GUI в мой класс, в котором был запущен метод, -GUI, который обновлял объект GUI. Так что не делайте этого.

Ответ 3

Как уже говорилось, у нас также была эта проблема. По-видимому, это вызвано обновлением пользовательского интерфейса с помощью метода javafx.concurrent.Service Task call(), хотя обновления были выполнены с помощью лямбда, переданного на Platform.runLater().

Итак, я переместил код обновления UI оттуда в Service On-Succeeded/Failed-Handlers, где он должен был быть в первую очередь. Это, похоже, устранило проблему для нас.