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

NPE while closing pop up window

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • 9
    • 8, 9
    • javafx
    • web

      ---------- BEGIN SOURCE ----------
      test.html
      ======

      <!DOCTYPE HTML>
      <html>
      <head>
          <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
      </head>
      <body>
      <div style="position:relative">
      <h2>Controls</h2>
      <button onclick="simulateRealTimeUpdates()">Start simulation</button>
      <button onclick="stopRealtime()">Stop simulation</button>
      <button onclick="openNewWindow()">Open new window</button>
      </div>

      <script>
          function simulateRealTimeUpdates() {
              window.service.data({
                  callback: function(dataStr) {
                      dataStr = null;
                  }
              });
          }

          function openNewWindow() {
              window.open('grid.html');
          }

          function stopRealtime() {
              window.service.cancelTimer();
          }
      </script>
      </body>
      </html>

      MemoryLeak2Service.java
      =====================

      package memoryLeak2;

      import javafx.application.Platform;
      import netscape.javascript.JSObject;

      import java.util.Arrays;
      import java.util.Timer;
      import java.util.TimerTask;

      public class MemoryLeak2Service {
          private final Timer timer = new java.util.Timer();
          private final int size = 1000000;
          private final String strBuffer;
          //private final char[] chrBuffer;
           
          public MemoryLeak2Service()
          {
           StringBuffer buffer = new StringBuffer(size);
           for (int i = 0; i < size; i++){
           buffer.append("A");
            }
          
           strBuffer = buffer.toString();
           //chrBuffer = strBuffer.toCharArray();
          }
           
          public void data(JSObject cb) {
              TimerTask tt = new TimerTask() {
                  public void run() {
                      Platform.runLater(new Runnable() {
                          @Override
                          public void run() {
                           // strBuffer - LEAKS, chrBuffer isn't leaking.
                           cb.call("callback", strBuffer);
                           //cb.call("callback", chrBuffer);
                          }
                      });
                  }
              };
              timer.schedule(tt, 1000, 100);
          }

          /**
           * Cancel timer
           */
          public void cancelTimer() {
              timer.cancel();
              timer.purge();

          }
      }

      MemoryLeak2.java
      ===============

      package memoryLeak2;

      import javafx.application.Application;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.concurrent.Worker.State;
      import javafx.event.EventHandler;
      import javafx.geometry.HPos;
      import javafx.geometry.VPos;
      import javafx.scene.Scene;
      import javafx.scene.layout.Region;
      import javafx.scene.paint.Color;
      import javafx.scene.web.PopupFeatures;
      import javafx.scene.web.WebEngine;
      import javafx.scene.web.WebEvent;
      import javafx.scene.web.WebView;
      import javafx.stage.Stage;
      import javafx.stage.WindowEvent;
      import javafx.util.Callback;
      import netscape.javascript.JSObject;

      public class MemoryLeak2 extends Application {

          public static final int WIDTH = 1000;
          public static final int HEIGHT = 600;

          @Override
          public void start(Stage stage) {
              create(stage);
          }

          public static void create(Stage stage) {
              // create the scene
              stage.setTitle("Original Web View");
              Scene scene = new Scene(new Browser(), WIDTH, HEIGHT, Color.web("#666970"));
              stage.setScene(scene);
              stage.show();


              stage.addEventHandler(WindowEvent.WINDOW_CLOSE_REQUEST, new EventHandler<WindowEvent>() {

                  @Override
                  public void handle(WindowEvent event) {
                      //Exit the application on first window close
                      System.exit(0);
                  }

              });



          }

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

      }

      class Browser extends Region {

          /**
           * html file to load
           */
          private String fileToLoad = "test.html";
          final WebView browser = new WebView();
          final WebEngine webEngine = browser.getEngine();
          private MemoryLeak2Service myService;

          public Browser() {
              //apply the styles
              getStyleClass().add("browser");



              webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {

                  @Override
                  public void changed(ObservableValue<? extends State> stateParam, State oldState, State newState) {

                      switch (newState) {
                      case READY:
                          break;
                      case SCHEDULED:
                          break;

                      case RUNNING:
                          break;

                      case CANCELLED:
                          break;

                      case SUCCEEDED:
                          if(!"about:blank".equals(webEngine.getLocation())) {
                              final JSObject window = (JSObject) webEngine.executeScript("window");
                              myService = new MemoryLeak2Service();
                              //set service as widow member
                              window.setMember("service", myService);
                              window.call("init");
                          }
                          break;

                      default:
                          break;
                      }
                  }
              });

              //alert to display some javascript logs
              webEngine.setOnAlert(new EventHandler<WebEvent<String>>() {

                  @Override
                  public void handle(WebEvent<String> webEvent) {
                      System.out.println(webEvent.getData());
                  }

              });

              // load the web page
              webEngine.load(Browser.class.getResource(fileToLoad).toExternalForm());

              getChildren().add(browser);
              webEngine.setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {
                  @Override
                  public WebEngine call(PopupFeatures param) {
                      Stage stg = new Stage();
                      stg.setTitle("Popup View");
                      final Browser root = new Browser();
                      Scene scene = new Scene(root, 800, 800, Color.web("#666970"));
                      stg.setScene(scene);
                      stg.show();
                      stg.addEventHandler(WindowEvent.WINDOW_CLOSE_REQUEST, new EventHandler<WindowEvent>() {

                          @Override
                          public void handle(WindowEvent event) {
                              if(root != null) {
                                  //On close cancel te timer
                                  root.getMyService().cancelTimer();
                                  //load null to free some memory
                                  root.getWebEngine().load(null);
                              }
                          }

                      });

                      return root.getWebEngine();
                  }
              });
          }

          public WebEngine getWebEngine() {
              return webEngine;
          }

          public MemoryLeak2Service getMyService() {
              return myService;
          }

          @Override protected void layoutChildren() {
              double w = getWidth();
              double h = getHeight();
              layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
          }

          @Override protected double computePrefWidth(double height) {
              return MemoryLeak2.HEIGHT;
          }

          @Override protected double computePrefHeight(double width) {
              return MemoryLeak2.WIDTH;
          }
      }


      ---------- END SOURCE ----------

      When we try to close the pop up window, below NPE observed:

      Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
              at Browser$3$1.handle(MemoryLeak2.java:140)
              at Browser$3$1.handle(MemoryLeak2.java:134)
              at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
              at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
              at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
              at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
              at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
              at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
              at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
              at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
              at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
              at javafx.event.Event.fireEvent(Event.java:198)
              at com.sun.javafx.stage.WindowPeerListener.closing(WindowPeerListener.java:93)
              at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:146)
              at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:40)
              at java.security.AccessController.doPrivileged(Native Method)
              at com.sun.javafx.tk.quantum.GlassWindowEventHandler.lambda$handleWindowEvent$4(GlassWindowEventHandler.java:175)
              at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
              at com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:173)
              at com.sun.glass.ui.Window.handleWindowEvent(Window.java:1313)
              at com.sun.glass.ui.Window.notifyClose(Window.java:1213)
              at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
              at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:189)
              at java.lang.Thread.run(Thread.java:804)

            mbilla Murali Billa
            mbilla Murali Billa
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: