On Thu, 20 Jul 2023 10:12:09 GMT, Prasanta Sadhukhan <psadhuk...@openjdk.org> 
wrote:

>> Due to transient datatype of scenePeer, it can become null which can result 
>> in NPE in scenarios where scene is continuously been reset and set, which 
>> warrants a null check, as is done in other places for the same variable.
>
> Prasanta Sadhukhan has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   Check FXEnabled initially

It's not entirely clear to me which thread is calling which methods in this 
class, and it would help to clearly mark which part of the class can be called 
from the FX thread and which parts from the AWT thread.

I also question how some of the other fields are used.  Many are marked 
`volatile` which is insufficient if you don't want to observe partial changes 
of x/y coordinates for example.

I agree with @mstr2 that a more careful analysis couldn't hurt. There seem to 
be only 2 threads involved, the AWT and FX Thread.  The fields they are sharing 
should be grouped and marked with a comment that they're shared. Any access to 
these fields should then be only while holding a lock.

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

> 150: 
> 151:     private static final Object LOCK = new Object();
> 152: 

I very much doubt it is the intention to synchronize on all JFXPanel instances, 
so this should not be static.

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

> 414:         }
> 415:         return lScenePeer;
> 416:     }

Suggestion:

    private EmbeddedSceneInterface getScenePeer() {
        synchronized(LOCK) {
            return scenePeer;
        }
    }

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

> 422:         }
> 423:         return lStagePeer;
> 424:     }

Suggestion:

    private EmbeddedStageInterface getStagePeer() {
        synchronized(LOCK) {
            return stagePeer;
        }
    }

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

> 1039: 
> 1040:         @Override
> 1041:         public void setEmbeddedStage(EmbeddedStageInterface 
> embeddedStage) {

These changes don't inspire confidence in this solution.  `stagePeer` is now no 
longer updated when `embeddedStage` is `null`.

IMHO they should be:

        @Override
        public void setEmbeddedStage(EmbeddedStageInterface embeddedStage) {
            synchronized(LOCK) {
                stagePeer = embeddedStage;
                if (stagePeer == null) {
                    return;
                }
            }

            if (pWidth > 0 && pHeight > 0) {
                embeddedStage.setSize(pWidth, pHeight);
            }
            invokeOnClientEDT(() -> {
                if (JFXPanel.this.isFocusOwner()) {
                    embeddedStage.setFocused(true, 
AbstractEvents.FOCUSEVENT_ACTIVATED);
                }
            });
            sendMoveEventToFX();
        }

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

> 1067: 
> 1068:         @Override
> 1069:         public void setEmbeddedScene(EmbeddedSceneInterface 
> embeddedScene) {

Same comment as with `setEmbeddedStage`; surrounding all accesses to 
`scenePeer` and `stagePeer` like this is not the way to do it, and looks 
incorrect.  I think this is more in the right direction:

        public void setEmbeddedScene(EmbeddedSceneInterface embeddedScene) {
            synchronized(LOCK) {
                if (scenePeer == embeddedScene) {
                    return;
                }
                scenePeer = embeddedScene;
            }

            if (embeddedScene == null) {
                invokeOnClientEDT(() -> {
                    if (dnd != null) {
                        dnd.removeNotify();
                        dnd = null;
                    }
                });
                return;
            }
            if (pWidth > 0 && pHeight > 0) {
                embeddedScene.setSize(pWidth, pHeight);
            }
            embeddedScene.setPixelScaleFactors((float) scaleFactorX, (float) 
scaleFactorY);

            invokeOnClientEDT(() -> {
                dnd = new SwingDnD(JFXPanel.this, scenePeer);
                dnd.addNotify();
                embeddedScene.setDragStartListener(dnd.getDragStartListener());
            });
        }

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

PR Review: https://git.openjdk.org/jfx/pull/1178#pullrequestreview-1541862971
PR Review Comment: https://git.openjdk.org/jfx/pull/1178#discussion_r1271120246
PR Review Comment: https://git.openjdk.org/jfx/pull/1178#discussion_r1271119728
PR Review Comment: https://git.openjdk.org/jfx/pull/1178#discussion_r1271120451
PR Review Comment: https://git.openjdk.org/jfx/pull/1178#discussion_r1271129358
PR Review Comment: https://git.openjdk.org/jfx/pull/1178#discussion_r1271131346

Reply via email to