I have (sometimes) the following exception in a loop when I exit my JavaFX application:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.tk.quantum.QuantumToolkit.isSupported(QuantumToolkit.java:1196)
at com.sun.javafx.application.PlatformImpl.isSupportedImpl(PlatformImpl.java:809)
at com.sun.javafx.application.PlatformImpl.isSupported(PlatformImpl.java:482)
at javafx.application.Platform.isSupported(Platform.java:168)
at com.sun.javafx.scene.input.PickResultChooser.processOffer(PickResultChooser.java:182)
at com.sun.javafx.scene.input.PickResultChooser.offer(PickResultChooser.java:143)
at javafx.scene.Node.impl_intersects(Node.java:4943)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2942)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2936)
at javafx.scene.Node.impl_pickNode(Node.java:4912)
at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899)
at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485)
at javafx.scene.Scene.pick(Scene.java:1942)
at javafx.scene.Scene.access$6700(Scene.java:159)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3711)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:432)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:187)
at java.lang.Thread.run(Thread.java:748)
It does not impact my app in another way, and it seems to happen when I'm quitting the app by clicking on the close button on my Window. When I'm quitting (and not always), I have several of this stack (last time it was 3, it's not an endless loop of course).
Note that I'm using Java 8, and I'm using a JavaFX Scene which is called from a non-JavaFX Thread (but using a Platform.runLater()
code), and added as a JFXPanel
in a Swing component. I'm create it in my main Thread by:
JFXPanel jfxPanel = new JFXPanel();
JFrame frame = new JFrame("GUI");
initGUI();
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(jfxPanel, BorderLayout.CENTER);
frame.setVisible(true);
All the JavaFX code is performed in the following code:
private void initGUI() {
Platform.runLater(new Runnable() {
@Override
public void run() {
initFX();
}
});
}
To answer a question in the comments, The com.sun.glass.ui.win.WinApplication.lambda$null$4
Stack element is in the following code (which explains why this exception happens in a loop):
@Override
protected void runLoop(final Runnable launchable) {
boolean isEventThread = AccessController
.doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread"));
int awareness = getDesiredAwarenesslevel();
ClassLoader classLoader = WinApplication.class.getClassLoader();
_setClassLoader(classLoader);
if (isEventThread) {
_init(awareness);
setEventThread(Thread.currentThread());
launchable.run();
return;
}
// Default stack size of Windows 32-bit application is 320K and which is
// not sufficient for few WebView based applications. Increase the stack
// size to 1MB to keep those apps running.
final long stackSize = AccessController.doPrivileged(
(PrivilegedAction<Long>)
() -> Long.getLong("glass.win.stackSize", PlatformUtil.isWindows32Bit() ? 1024 * 1024 : 0));
final Thread toolkitThread =
AccessController.doPrivileged((PrivilegedAction<Thread>) () -> new Thread(
null,
() -> {
_init(awareness);
_runLoop(launchable); // this is here
},
"WindowsNativeRunloopThread",
stackSize));
setEventThread(toolkitThread);
toolkitThread.start();
}
It's the _runLoop(launchable);
call.
The origin of the NPE seems to be in this code:
@Override
public boolean isSupported(ConditionalFeature feature) {
switch (feature) {
case SCENE3D:
return GraphicsPipeline.getPipeline().is3DSupported(); // this is here
...
Which means that the GraphicsPipeline.getPipeline()
method is called but returns null in my case "when I'm quitting the app".
I looked in the GraphicsPipeline
class. The getPipeline()
method is:
public static GraphicsPipeline getPipeline() {
return installedPipeline;
}
The installedPipeline
is set to null only when calling:
public void dispose() {
notifyDisposeHooks();
installedPipeline = null;
}
So it appear that I'm calling GraphicsPipeline.dispose()
indirectly when quitting my app, but the loop called through public void runLoop(final Runnable launchable)
method might not be interrupted yet.
I have absolutely no problem when I use the app, its just when I'm quitting that I (sometimes) have this exception. What did I do wrong?