Critical error when showing and hiding stage or popup
Kevin Rushforth
kevin.rushforth at oracle.com
Fri Sep 3 15:09:01 UTC 2021
FWIW, here is the modified code that will run indefinitely (note that
there is an extra "9" in the loop count...I got tired of watching it
after about 200,000 times):
Thread t = new Thread(() -> {
for (int i = 0; i < 999999; i++) {
final int _i = i;
Platform.runLater(() -> {
popOver.show(scene.getRoot(), 1, 1);
popOver.hide();
System.out.println(_i);
});
}
});
t.start();
And while that code is very artificial, too, it shows that we are not
leaking Windows class objects in general.
-- Kevin
On 9/3/2021 7:34 AM, Kevin Rushforth wrote:
> I missed seeing the message yesterday. He did file a bug at
> bugreport.java.com, which ended up here:
>
> https://bugs.openjdk.java.net/browse/JDK-8273319
>
> I just evaluated it, and closed it as "not an issue". As I wrote in
> the bug report:
>
> ---------------------------------------------
> "The test application is starving the event queue by running the show
> / hide in a tight loop on the JavaFX Application Thread. This means
> that no other operations, such as event processing, repainting the
> screen, or processing any queued messages, can occur. When a window is
> closed, we queue up an message to unregister the Window class to
> ensure that the class is no longer referenced before unregistering it
> (else it will fail). Since it is given no opportunity to run, we will
> leak and eventually run out of Windows class objects.
>
> A modified test program that uses Platform.runLater to avoid starving
> the event queue does not encounter this problem. I ran it for about
> 200,000 iterations of the loop with no problems, and verified that the
> Regisgter / Unregister Class methods are correctly balanced.
>
> There *might* be something we could do to workaround this, but this is
> the result of a poorly behaved application test program. Instead, the
> application should be rewritten to not run code like this in a tight
> loop on the JavaFX Application Thread. I can't imagine the case where
> a real application would need to do what this stress test is doing."
> ---------------------------------------------
>
> Do you have a non-pathological test case (meaning one where you don't
> show/hide in a loop) that shows this leak? If so, I can reopen the bug
> and we'll take a look.
>
> -- Kevin
>
>
> On 9/3/2021 6:50 AM, Nir Lisker wrote:
>> I would submit it to bugreport.java.com.
>>
>> On Thu, Sep 2, 2021 at 9:08 PM Troels Skytte Kaspersen <trkas at eg.dk>
>> wrote:
>>
>>> Hi,
>>>
>>> We have received many complaints from our customers that the popups are
>>> not shown anymore after a period of time.
>>>
>>> I have then created a simple piece of code that result in the error our
>>> customers get:
>>>
>>> package test;
>>>
>>> import javafx.application.Application;
>>> import javafx.scene.Scene;
>>> import javafx.scene.layout.StackPane;
>>> import javafx.stage.Popup;
>>> import javafx.stage.Stage;
>>>
>>> public class TestFX extends Application {
>>>
>>> @Override
>>> public void start(Stage primaryStage) {
>>> System.out.println("javafx.runtime.version: " +
>>> System.getProperties().get("javafx.runtime.version"));
>>> Stage stage = new Stage();
>>> Scene scene = new Scene(new StackPane());
>>> stage.setScene(scene);
>>> stage.show();
>>> Popup popOver = new Popup();
>>> for (int i = 0; i < 99999; i++) {
>>> popOver.show(scene.getRoot(), 1, 1);
>>> popOver.hide();
>>> System.out.println(i);
>>> }
>>> }
>>>
>>> public static void main(String[] args) {
>>> launch(args);
>>> }
>>> }
>>>
>>> I use javafx 16+8
>>>
>>> If I run the code, it will result in error after various iterations:
>>>
>>> Exception in Application start method
>>> Exception in thread "JavaFX Application Thread"
>>> java.lang.NullPointerException
>>> at
>>> javafx.base/com.sun.javafx.binding.ExpressionHelper.removeListener(ExpressionHelper.java:73)
>>>
>>> at
>>> javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.removeListener(ReadOnlyBooleanPropertyBase.java:67)
>>>
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.unbindOwnerFocusedProperty(PopupWindow.java:895)
>>>
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.doVisibleChanged(PopupWindow.java:542)
>>>
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow$1.doVisibleChanged(PopupWindow.java:111)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.stage.PopupWindowHelper.visibleChangedImpl(PopupWindowHelper.java:63)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.stage.WindowHelper.visibleChanged(WindowHelper.java:77)
>>>
>>> at
>>> javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1160)
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
>>>
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
>>>
>>> at
>>> javafx.graphics/javafx.stage.Window.setShowing(Window.java:1187)
>>> at
>>> javafx.graphics/javafx.stage.Window.hide(Window.java:1212)
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.hide(PopupWindow.java:486)
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.lambda$new$0(PopupWindow.java:147)
>>>
>>> at
>>> javafx.base/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:86)
>>>
>>> at
>>> javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:181)
>>>
>>> at
>>> javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
>>>
>>> at
>>> javafx.graphics/javafx.scene.Node$TreeShowingPropertyReadOnly.invalidate(Node.java:8479)
>>>
>>> at
>>> javafx.graphics/javafx.scene.Node.setTreeShowing(Node.java:8436)
>>> at
>>> javafx.graphics/javafx.scene.Node.updateTreeShowing(Node.java:8427)
>>> at
>>> javafx.graphics/javafx.scene.Node.lambda$new$2(Node.java:1010)
>>> at
>>> javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
>>>
>>> at
>>> javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
>>>
>>> at
>>> javafx.base/javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:78)
>>>
>>> at
>>> javafx.base/javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:103)
>>>
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:111)
>>>
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
>>>
>>> at
>>> javafx.graphics/javafx.stage.Window.setShowing(Window.java:1187)
>>> at
>>> javafx.graphics/javafx.stage.Window.hide(Window.java:1212)
>>> at
>>> javafx.graphics/com.sun.javafx.stage.WindowPeerListener.closed(WindowPeerListener.java:105)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:144)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:40)
>>>
>>> at
>>> java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.GlassWindowEventHandler.lambda$handleWindowEvent$4(GlassWindowEventHandler.java:176)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:174)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.Window.handleWindowEvent(Window.java:1336)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.Window.notifyDestroy(Window.java:1250)
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinWindow._close(Native Method)
>>> at
>>> javafx.graphics/com.sun.glass.ui.Window.close(Window.java:352)
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinWindow.close(WinWindow.java:316)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.Application.terminate(Application.java:394)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$exit$13(QuantumToolkit.java:831)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithRenderLock(QuantumToolkit.java:430)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.exit(QuantumToolkit.java:827)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$tkExit$16(PlatformImpl.java:614)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:474)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447)
>>>
>>> at
>>> java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native
>>> Method)
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
>>>
>>> at java.base/java.lang.Thread.run(Thread.java:831)
>>> java.lang.reflect.InvocationTargetException
>>> at
>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
>>> Method)
>>> at
>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
>>>
>>> at
>>> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>
>>> at
>>> java.base/java.lang.reflect.Method.invoke(Method.java:567)
>>> at
>>> javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
>>>
>>> at
>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
>>> Method)
>>> at
>>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
>>>
>>> at
>>> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>
>>> at
>>> java.base/java.lang.reflect.Method.invoke(Method.java:567)
>>> at
>>> java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1071)
>>>
>>> Caused by: java.lang.RuntimeException: Exception in Application start
>>> method
>>> at
>>> javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
>>>
>>> at java.base/java.lang.Thread.run(Thread.java:831)
>>> Caused by: java.lang.RuntimeException: could not create platform window
>>> at
>>> javafx.graphics/com.sun.glass.ui.Window.<init>(Window.java:294)
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinWindow.<init>(WinWindow.java:54)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinApplication.createWindow(WinApplication.java:219)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.initPlatformWindow(WindowStage.java:201)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.init(WindowStage.java:143)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.createTKPopupStage(QuantumToolkit.java:678)
>>>
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.doVisibleChanging(PopupWindow.java:514)
>>>
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow$1.doVisibleChanging(PopupWindow.java:107)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.stage.PopupWindowHelper.visibleChangingImpl(PopupWindowHelper.java:57)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.stage.WindowHelper.visibleChanging(WindowHelper.java:73)
>>>
>>> at
>>> javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1065)
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
>>>
>>> at
>>> javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
>>>
>>> at
>>> javafx.graphics/javafx.stage.Window.setShowing(Window.java:1187)
>>> at
>>> javafx.graphics/javafx.stage.Window.show(Window.java:1202)
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.showImpl(PopupWindow.java:472)
>>> at
>>> javafx.graphics/javafx.stage.PopupWindow.show(PopupWindow.java:417)
>>> at test.TestFX.start(TestFX.java:35)
>>> at
>>> javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:474)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447)
>>>
>>> at
>>> java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
>>>
>>> at
>>> javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
>>>
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native
>>> Method)
>>> at
>>> javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
>>>
>>> ... 1 more
>>> Exception running application test.TestFX
>>> B_
>>>
>>> I have tried javafx version down to javafx 11 and the error always
>>> occurs
>>> at some point.
>>>
>>> I would consider this a very critical error. The workaround seems to
>>> just
>>> set the opacity to 0 instead of hide(), but still I expect this code
>>> to run
>>> until the end..
>>>
>>> Venlig hilsen / best regards
>>>
>>> Troels Skytte Kaspersen
>>> Software Developer
>>> ASPECT4 Development
>>>
>>> EG A/S ∙ Finsensvej 3 ∙ 7430 Ikast
>>> T: +45 7013 2211 ∙ D: +45 7260 2235
>>> F: +45 7013 2299 ∙ M: +45 2085 9209
>>> E-mail: trkas at eg.dk<mailto:trkas at eg.dk> ∙ web:
>>> www.eg.dk<http://www.eg.dk>
>>> Read our Privacy
>>> Policy<https://global.eg.dk/about-eg/treatment-of-data/>
>>>
>
More information about the openjfx-dev
mailing list