On Tue, 18 Nov 2025 13:24:31 GMT, Prasanta Sadhukhan <[email protected]> 
wrote:

>> NPE is seen while accessing transient "scenePeer" variable between reads..
>> Fix is made to store it in a temp variable rather than reading it twice 
>> since the value can change between successive reads in many places it is 
>> accessed.
>> Also some debug logs added to be enabled via `jfxpanel.debug` property
>
> Prasanta Sadhukhan has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   temp-var handling in few other methods

I left a few comments inline. I still want to look more closely at the 
`sendXxxxxEventToFX()` methods to see if there are any problems using a stale 
value of scenePeer() or stagePeer(). I do think this PR improves the situation 
by avoiding spurious NPEs, so if further analysis doesn't show any additional 
problems, it it probably reasonable to proceed with this PR and file a 
follow-on bug to do a proper MT design for JFXPanel.


I also want do some additional testing.

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java line 156:

> 154:     private transient volatile EmbeddedWindow stage;
> 155: 
> 156:     private transient volatile Scene scene;

Minor: I would remove the blank line between these two declarations to make it 
clear that the comment applies to both.

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java line 974:

> 972:                         getScene().getFocusOwner() != null &&
> 973:                         getScene().getFocusOwner().isFocused()) {
> 974:                     hStagePeer.focusUngrab();

This can be reverted. `stagePeer` is only accessed on the FX thread.

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java line 996:

> 994:                             // some reason they didn't install the grab 
> when
> 995:                             // they were shown.
> 996:                             hStagePeer.focusUngrab();

This can be reverted. `stagePeer` is only accessed on the FX thread.

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java line 1023:

> 1021:             }
> 1022:         });
> 1023:         sendMoveEventToFX();

This is not an equivalent change, since `sendMoveEventToFX()` can now happen 
before `stage.show()` and will also happen unconditionally even if the stage is 
null or already showing. Rather than moving it out of the runOnFxThread block, 
leave it where it is and call `runOnEDT` like this:


        SwingNodeHelper.runOnFxThread(() -> {
            if ((stage != null) && !stage.isShowing()) {
                stage.show();
                SwingNodeHelper.runOnEDT(() -> sendMoveEventToFX());
            }
        });

modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java line 1078:

> 1076:             stagePeer = embeddedStage;
> 1077:             var hStagePeer = stagePeer;
> 1078:             if (hStagePeer == null) {

If this is always invoked from the FX thread, you don't need to locally capture 
the peers.

tests/system/src/test/java/test/javafx/embed/swing/JFXPanelNPETest.java line 
105:

> 103:             Thread.sleep(100);
> 104:         }
> 105:         System.out.println("failure = " + failure.get());

This print can be removed.

-------------

PR Review: https://git.openjdk.org/jfx/pull/1968#pullrequestreview-3478854934
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539008637
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539028674
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539029530
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539054147
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539059009
PR Review Comment: https://git.openjdk.org/jfx/pull/1968#discussion_r2539066037

Reply via email to