You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2019/05/04 11:05:13 UTC
[netbeans-html4j] 06/07: Avoid memory leaks via ChangeListener.
Workaround FX problem on JDK11.
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 <ja...@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-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists