A DESCRIPTION OF THE PROBLEM :
NullpointerException in #paintComponent
This is becaue of a Race Condition in JFXPanel.HostContainer. Since the values stagePeer and scenePeer are read in the swing thread, it is not safe to write them in the javafx thread.
java.lang.NullPointerException: Cannot invoke "com.sun.javafx.embed.EmbeddedSceneInterface.getPixels(java.nio.IntBuffer, int, int)" because "this.scenePeer" is null
at javafx.embed.swing.JFXPanel.paintComponent(JFXPanel.java:748)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached Code, it simulates an UI under heavy load.
The UI should flicker, but no Exceptions should be thrown as all calls are placed on the correct thread.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code completes without Exceptions/failure JFXPanel.HostContainer.
ACTUAL -
Code throws Exceptions.
---------- BEGIN SOURCE ----------
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class Dummy {
private static WebView webView;
private static JFXPanel contentPane;
private static AtomicBoolean failure;
public static void main(String[] args) throws Throwable {
failure = new AtomicBoolean(false);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
failure.set(true);
}
});
SwingUtilities.invokeAndWait(Dummy::createUI);
for (int i = 0; i < 3000; i++) {
SwingUtilities.invokeLater(contentPane::repaint);
Platform.runLater(() -> contentPane.setScene(null));
Thread.sleep(1);
Platform.runLater(() -> contentPane.setScene(webView.getScene()));
Thread.sleep(1);
}
System.out.println("failure = " + failure.get());
}
protected static void createUI() {
final var jFrame = new JFrame();
contentPane = new JFXPanel();
Platform.runLater(() -> fx(contentPane));
jFrame.setContentPane(contentPane);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(400,400);
jFrame.setVisible(true);
}
private static void fx(final JFXPanel contentPane) {
webView = new WebView();
final var engine = webView.getEngine();
engine.loadContent("hello!");
contentPane.setScene(new Scene(webView));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
set -Djavafx.embed.singleThread=true -> No Multithreading issues if there is only one thread.
FREQUENCY : always
NullpointerException in #paintComponent
This is becaue of a Race Condition in JFXPanel.HostContainer. Since the values stagePeer and scenePeer are read in the swing thread, it is not safe to write them in the javafx thread.
java.lang.NullPointerException: Cannot invoke "com.sun.javafx.embed.EmbeddedSceneInterface.getPixels(java.nio.IntBuffer, int, int)" because "this.scenePeer" is null
at javafx.embed.swing.JFXPanel.paintComponent(JFXPanel.java:748)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:907)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1083)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached Code, it simulates an UI under heavy load.
The UI should flicker, but no Exceptions should be thrown as all calls are placed on the correct thread.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code completes without Exceptions/failure JFXPanel.HostContainer.
ACTUAL -
Code throws Exceptions.
---------- BEGIN SOURCE ----------
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class Dummy {
private static WebView webView;
private static JFXPanel contentPane;
private static AtomicBoolean failure;
public static void main(String[] args) throws Throwable {
failure = new AtomicBoolean(false);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
failure.set(true);
}
});
SwingUtilities.invokeAndWait(Dummy::createUI);
for (int i = 0; i < 3000; i++) {
SwingUtilities.invokeLater(contentPane::repaint);
Platform.runLater(() -> contentPane.setScene(null));
Thread.sleep(1);
Platform.runLater(() -> contentPane.setScene(webView.getScene()));
Thread.sleep(1);
}
System.out.println("failure = " + failure.get());
}
protected static void createUI() {
final var jFrame = new JFrame();
contentPane = new JFXPanel();
Platform.runLater(() -> fx(contentPane));
jFrame.setContentPane(contentPane);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setSize(400,400);
jFrame.setVisible(true);
}
private static void fx(final JFXPanel contentPane) {
webView = new WebView();
final var engine = webView.getEngine();
engine.loadContent("hello!");
contentPane.setScene(new Scene(webView));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
set -Djavafx.embed.singleThread=true -> No Multithreading issues if there is only one thread.
FREQUENCY : always
- links to
-
Review openjdk/jfx/1178