Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8088420

JavaFX WebView memory leak via EventListener

XMLWordPrintable

    • web

        Hi,

        I found out that calling eventtarget.removeEventListener doesn't remove the Eventlistener so it's being garbage collected.

        If you run this code:
        import javafx.application.Application;
        import javafx.beans.value.ChangeListener;
        import javafx.beans.value.ObservableValue;
        import javafx.concurrent.Worker.State;
        import javafx.event.ActionEvent;
        import javafx.event.EventHandler;
        import javafx.scene.Scene;
        import javafx.scene.control.Button;
        import javafx.scene.layout.BorderPane;
        import javafx.scene.layout.HBox;
        import javafx.scene.layout.Pane;
        import javafx.scene.web.WebView;
        import javafx.stage.Stage;

        import org.w3c.dom.events.Event;
        import org.w3c.dom.events.EventListener;
        import org.w3c.dom.events.EventTarget;

        public class WebViewTest extends Application{

        private Scene scene;
        private Pane top;
        private Pane bottom;
        private EventListener listener;

        public static void main(String[] args) throws Exception {
        launch(args);
        }

        @Override
        public void start(Stage primaryStage) throws Exception {

        primaryStage.setScene(new Scene(new BorderPane()));
        scene = primaryStage.getScene();
        top = new HBox();
        ((BorderPane)scene.getRoot()).setTop(top);
        bottom = new HBox();
        ((BorderPane)scene.getRoot()).setBottom(bottom);
        addWebView();
        Button but = new Button();
        but.setText("add and remove eventlistener");
        but.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
        addWebView();
        }
        });
        bottom.getChildren().add(but);
        primaryStage.show();

        }

        public void addWebView() {
        top.getChildren().clear();
        final WebView webView = new WebView();
        top.getChildren().add(webView);
        webView.getEngine().loadContent("HELLO");
        listener = new EventListener() {

        @Override
        public void handleEvent(Event evt) {
        }
        };
        webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {

        @Override
        public void changed(ObservableValue<? extends State> arg0, State arg1, State arg2) {
        if (arg2 == State.SUCCEEDED) {
        EventTarget target = (EventTarget) webView.getEngine().getDocument().getDocumentElement();
        target.addEventListener("keydown",listener , false);
        webView.getEngine().getLoadWorker().stateProperty().removeListener(this);
        target.removeEventListener("keydown",listener , false);
        listener = null;
        }

        }
        });
        }
        }

        And clicking on the button for example 10 times, then when you look in for example JProfiler, so can see 10 instances of EventListenerImpl, and it never decreases.. Isn't this a bug?

        Best regards
        Troels

              jbhaskar Jay Bhaskar
              duke J. Duke
              Votes:
              1 Vote for this issue
              Watchers:
              10 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported: