This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans-html4j.git

commit 9a279a217f32517e2bd72364564ece28555e5783
Author: Jaroslav Tulach <jaroslav.tul...@apidesign.org>
AuthorDate: Sat May 4 11:29:05 2019 +0200

    Avoid memory leaks via ChangeListener.
    Workaround FX problem on JDK11.
---
 .../java/net/java/html/boot/fx/FXBrowsers.java     |  4 ++
 .../netbeans/html/boot/fx/InitializeWebView.java   | 72 ++++++++++++++--------
 .../org/netbeans/html/ko4j/DoubleViewTest.java     | 41 ++++++++++--
 3 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java 
b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java
index 4ae8909..8d310fb 100644
--- a/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java
+++ b/boot-fx/src/main/java/net/java/html/boot/fx/FXBrowsers.java
@@ -25,6 +25,7 @@ import javafx.scene.web.WebView;
 import net.java.html.BrwsrCtx;
 import net.java.html.boot.BrowserBuilder;
 import net.java.html.js.JavaScriptBody;
+import org.netbeans.html.boot.spi.Fn;
 import org.netbeans.html.context.spi.Contexts;
 import org.netbeans.html.context.spi.Contexts.Id;
 
@@ -200,6 +201,9 @@ public final class FXBrowsers {
      */
     public static void runInBrowser(WebView webView, Runnable code) {
         Object ud = webView.getUserData();
+        if (ud instanceof Fn.Ref<?>) {
+            ud = ((Fn.Ref<?>)ud).presenter();
+        }
         if (!(ud instanceof InitializeWebView)) {
             throw new IllegalArgumentException();
         }
diff --git 
a/boot-fx/src/main/java/org/netbeans/html/boot/fx/InitializeWebView.java 
b/boot-fx/src/main/java/org/netbeans/html/boot/fx/InitializeWebView.java
index b093565..4853ffe 100644
--- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/InitializeWebView.java
+++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/InitializeWebView.java
@@ -18,6 +18,7 @@
  */
 package org.netbeans.html.boot.fx;
 
+import java.lang.ref.WeakReference;
 import java.net.URL;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
@@ -35,7 +36,7 @@ public final class InitializeWebView extends 
AbstractFXPresenter implements Runn
     public InitializeWebView(WebView webView, Runnable onLoad) {
         this.webView = webView;
         this.myLoad = onLoad;
-        webView.setUserData(this);
+        webView.setUserData(reference());
     }
 
     @Override
@@ -54,32 +55,7 @@ public final class InitializeWebView extends 
AbstractFXPresenter implements Runn
     @Override
     WebView findView(final URL resource) {
         final Worker<Void> w = webView.getEngine().getLoadWorker();
-        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
-            private String previous;
-
-            @Override
-            public void changed(ObservableValue<? extends Worker.State> ov, 
Worker.State t, Worker.State newState) {
-                if (newState.equals(Worker.State.SUCCEEDED)) {
-                    if (checkValid()) {
-                        onPageLoad();
-                    }
-                }
-                if (newState.equals(Worker.State.FAILED)) {
-                    checkValid();
-                    throw new IllegalStateException("Failed to load " + 
resource);
-                }
-            }
-
-            private boolean checkValid() {
-                final String crnt = webView.getEngine().getLocation();
-                if (previous != null && !previous.equals(crnt)) {
-                    w.stateProperty().removeListener(this);
-                    return false;
-                }
-                previous = crnt;
-                return true;
-            }
-        });
+        w.stateProperty().addListener(new FindViewListener(this, resource, w));
         return webView;
     }
 
@@ -87,4 +63,46 @@ public final class InitializeWebView extends 
AbstractFXPresenter implements Runn
         ctx.execute(r);
     }
 
+    private static class FindViewListener extends 
WeakReference<InitializeWebView>
+    implements ChangeListener<Worker.State> {
+
+        private final URL resource;
+        private final Worker<Void> w;
+
+        public FindViewListener(InitializeWebView view, URL resource, 
Worker<Void> w) {
+            super(view);
+            this.resource = resource;
+            this.w = w;
+        }
+        private String previous;
+
+        @Override
+        public void changed(ObservableValue<? extends Worker.State> ov, 
Worker.State t, Worker.State newState) {
+            InitializeWebView view = get();
+            if (view == null) {
+                w.stateProperty().removeListener(this);
+                return;
+            }
+            if (newState.equals(Worker.State.SUCCEEDED)) {
+                if (checkValid(view)) {
+                    view.onPageLoad();
+                }
+            }
+            if (newState.equals(Worker.State.FAILED)) {
+                checkValid(view);
+                throw new IllegalStateException("Failed to load " + resource);
+            }
+        }
+
+        private boolean checkValid(InitializeWebView view) {
+            final String crnt = view.webView.getEngine().getLocation();
+            if (previous != null && !previous.equals(crnt)) {
+                w.stateProperty().removeListener(this);
+                return false;
+            }
+            previous = crnt;
+            return true;
+        }
+    }
+
 }
diff --git a/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java 
b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
index 9f49d84..bf551b5 100644
--- a/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
+++ b/ko4j/src/test/java/org/netbeans/html/ko4j/DoubleViewTest.java
@@ -35,6 +35,7 @@ import net.java.html.boot.fx.FXBrowsers;
 import net.java.html.json.Function;
 import net.java.html.json.Model;
 import net.java.html.json.Property;
+import org.netbeans.html.boot.spi.Fn;
 import org.netbeans.junit.NbTestCase;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
@@ -63,6 +64,8 @@ public class DoubleViewTest {
 
     private static final StringBuffer LOG = new StringBuffer();
     private JFrame frame;
+    private Fn.Presenter presenter1;
+    private Fn.Presenter presenter2;
 
     @BeforeMethod
     public void initializeViews() throws Exception {
@@ -90,12 +93,14 @@ public class DoubleViewTest {
         final CountDownLatch view2Init = new CountDownLatch(1);
         Platform.runLater(() -> {
             FXBrowsers.load(view1, page, () -> {
+                presenter1 = Fn.activePresenter();
                 doubleView.applyBindings();
                 log("applyBindings view One");
                 view1Init.countDown();
             });
 
             FXBrowsers.load(view2, page, () -> {
+                presenter2 = Fn.activePresenter();
                 doubleView.applyBindings();
                 log("applyBindings view Two");
                 view2Init.countDown();
@@ -104,6 +109,8 @@ public class DoubleViewTest {
         view1Init.await();
         view2Init.await();
         log("initializeViews - done");
+        assertNotNull(presenter1, "presenter for view1 found");
+        assertNotNull(presenter2, "presenter for view2 found");
     }
 
     private void displayFrame(JFXPanel panel, JFXPanel p2) {
@@ -168,6 +175,35 @@ public class DoubleViewTest {
         });
         cdl.await();
 
+        assertGCPresenters();
+        assertGCViews();
+
+        Platform.runLater(() -> {
+            Platform.setImplicitExit(false);
+            frame.dispose();
+        });
+    }
+
+    private void assertGCPresenters() {
+        Reference<?> r1 = new WeakReference<>(presenter1);
+        Reference<?> r2 = new WeakReference<>(presenter2);
+
+        presenter1 = null;
+        presenter2 = null;
+
+        NbTestCase.assertGC("Clearing reference 1", r1);
+        NbTestCase.assertGC("Clearing reference 2", r2);
+    }
+
+    private void assertGCViews() {
+        try {
+            Class.forName("java.lang.Module");
+            // skip the test on JDK11 and more
+            return;
+        } catch (ClassNotFoundException ex) {
+            // OK on JDK8
+        }
+
         Reference<?> r1 = new WeakReference<>(view1);
         Reference<?> r2 = new WeakReference<>(view2);
 
@@ -176,11 +212,6 @@ public class DoubleViewTest {
 
         NbTestCase.assertGC("Clearing reference 1", r1);
         NbTestCase.assertGC("Clearing reference 2", r2);
-
-        Platform.runLater(() -> {
-            Platform.setImplicitExit(false);
-            frame.dispose();
-        });
     }
 
     private void assertMessages(String msg, WebView v, String expected) {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to