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

JavaVM crashes when loading a certain WebPage inside JavaFx WebView

    XMLWordPrintable

Details

    • web
    • x86
    • generic

    Description

      FULL PRODUCT VERSION :
      java version "1.8.0_144"
      Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
      Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.15063]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      I Have tested this using different Java Versions. The last known version is 8u121.
      Also, it does not work with the actual Java9 prerelease 9+181 .

      A DESCRIPTION OF THE PROBLEM :
      When trying to load some webcontent JavaFx WebView, the vm crashes.
      When it happens, I do not get any useful output on the console nor do I get a hs_err_pid* file, the application just crashes with the Window's "There is a problem with the application...". On the console, I get "Process finished with exit code 255", but no stacktrace, no warning, nothing.

      REGRESSION. Last worked in version 8u121

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.8.0_121"
      Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the example Application.
      Click menu "Test", "YWorks demo".
      Alternatively, you could also load the page http://live.yworks.com/demobrowser/index.html#Business-Process-Models
      using the URL field

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      After the application starts, the oracle hompage is correctly loaded, everything fine.
      After clicking "YWorks demo", the page loads and displays a BPMN Swimlane diagram with editor abilities.
      ACTUAL -
      After clicking "YWorks demo", the page starts to load but does not yet display a diagram. After a few seconds, the application crashes.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      As written, there is no hs_err_pid file written. Also nothing in the console.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      /*
       * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
       *
       * Redistribution and use in source and binary forms, with or without
       * modification, are permitted provided that the following conditions
       * are met:
       *
       * - Redistributions of source code must retain the above copyright
       * notice, this list of conditions and the following disclaimer.
       *
       * - Redistributions in binary form must reproduce the above copyright
       * notice, this list of conditions and the following disclaimer in the
       * documentation and/or other materials provided with the distribution.
       *
       * - Neither the name of Oracle or the names of its
       * contributors may be used to endorse or promote products derived
       * from this software without specific prior written permission.
       *
       * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       */

      package test;

      import javafx.application.Platform;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.collections.ObservableList;
      import javafx.embed.swing.JFXPanel;
      import javafx.event.EventHandler;
      import javafx.scene.Scene;
      import javafx.scene.web.*;

      import javax.net.ssl.*;
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.*;
      import java.net.MalformedURLException;
      import java.net.URL;
      import java.security.KeyManagementException;
      import java.security.NoSuchAlgorithmException;
      import java.security.cert.X509Certificate;
      import java.text.MessageFormat;

      import static javafx.concurrent.Worker.State.FAILED;

      /**
       * Got that demo from https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/swing-fx-interoperability.htm
       * Tested if using YWorks and our own WebExplorer is working (open the page using the menu...).
       * Also tested if the browser content overlaps the swing components (it doesn't).
       * Also, memory consuption is ok.
       *
       * This demo worked in 2016 when running it with Java8u121 and before.
       * It seems to have stopped working with Java8u131.
       * Also it does not work with Java9_181.
       *
       * @author mschlegel
       */
      public class SimpleSwingBrowser extends JFrame {

        private final JFXPanel jfxPanel = new JFXPanel();
        private WebEngine engine;

        private final JPanel panel = new JPanel(new BorderLayout());
        private final JLabel lblStatus = new JLabel();
        private final JLabel memoryLabel = new JLabel();


        private final JButton btnGo = new JButton("Go");
        private final JTextField txtURL = new JTextField();
        private final JProgressBar progressBar = new JProgressBar();

        public SimpleSwingBrowser() {
          super();
          //switch off certificate checks
          TrustManager trm = new X509TrustManager() {
            @Override public X509Certificate[] getAcceptedIssuers() {
              return null;
            }

            @Override public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }

            @Override public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
          };
          HostnameVerifier nullVerifier = new HostnameVerifier() {
            @Override public boolean verify(String hostname, SSLSession session) {
              return true;
            }
          };
          HttpsURLConnection.setDefaultHostnameVerifier(nullVerifier);
          SSLContext sc;
          try{
            sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[]{trm}, null);
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
          }catch(NoSuchAlgorithmException e){
            e.printStackTrace();
          }catch(KeyManagementException e){
            e.printStackTrace();
          }

          initComponents();
        }

        private void initComponents() {
          //mar: test overlay (lightweight/heavyweight)
          JMenuBar mBar = new JMenuBar();
          JMenu menu = new JMenu("Test");
          JMenuItem mItem = new JMenuItem("Go");
          JMenuItem mItemBack = new JMenuItem("Back");
          JMenuItem mItemForward = new JMenuItem("Forward");
          JMenuItem mItemInfo = new JMenuItem("Info");
          JMenuItem mItemYWorks = new JMenuItem("Load YWorks Demo...");
          menu.add(mItem);
          menu.add(mItemBack);
          menu.add(mItemForward);
          menu.addSeparator();
          menu.add(mItemInfo);
          menu.addSeparator();
          menu.add(mItemYWorks);
          mBar.add(menu);
          this.setJMenuBar(mBar);

          ActionListener al = new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
              loadURL(txtURL.getText());
            }
          };


          mItemInfo.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
              Platform.runLater(new Runnable() {
                @Override public void run() {
                  String tmp = engine.getUserAgent();
                  SwingUtilities.invokeLater(()->
                          JOptionPane.showMessageDialog(SimpleSwingBrowser.this, "Browser used: " + tmp)
                  );
                }
              });
            }
          });
          mItemBack.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
              goBack();
            }
          });
          mItemBack.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK));
          mItemForward.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
              goForward();
            }
          });
          mItemForward.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK));
          mItemYWorks.setToolTipText("Loads http://live.yworks.com/demobrowser/index.html#Business-Process-Models");
          mItemYWorks.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
              txtURL.setText("http://live.yworks.com/demobrowser/index.html#Business-Process-Models");
              al.actionPerformed(e);
            }
          });
          memoryLabel.setToolTipText("Click to run Garbagecollector");
          memoryLabel.addMouseListener(new MouseAdapter() {
            @Override public void mouseClicked(MouseEvent e) {
              Thread t = new Thread() {
                @Override public void run() {
                  System.gc();
                  refreshMemoryStatus();
                }
              };
              t.start();
            }
          });

          createScene();

          mItem.addActionListener(al);
          btnGo.addActionListener(al);
          txtURL.addActionListener(al);

          progressBar.setPreferredSize(new Dimension(150, 18));
          progressBar.setStringPainted(true);

          JPanel topBar = new JPanel(new BorderLayout(5, 0));
          topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
          topBar.add(txtURL, BorderLayout.CENTER);
          topBar.add(btnGo, BorderLayout.EAST);

          JPanel statusBar = new JPanel(new BorderLayout(5, 0));
          statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
          statusBar.add(memoryLabel, BorderLayout.WEST);
          statusBar.add(lblStatus, BorderLayout.CENTER);
          statusBar.add(progressBar, BorderLayout.EAST);

          panel.add(topBar, BorderLayout.NORTH);
          panel.add(jfxPanel, BorderLayout.CENTER);
          panel.add(statusBar, BorderLayout.SOUTH);

          getContentPane().add(panel);

          setPreferredSize(new Dimension(1024, 600));
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          pack();

          new MemoryWatcher().start();
        }

        class MemoryWatcher extends Thread {
          public MemoryWatcher() {
            super("TEMemoryWatcher"); //$NON-NLS-1$
            super.setPriority(Thread.MIN_PRIORITY);
          }

          @Override public void run() {
            while (true){
              refreshMemoryStatus();
              try{
                Thread.sleep(15000);
              }catch(InterruptedException ex){
                System.err.println("MemoryWatcher interrupted.");
                ex.printStackTrace();
              }
            }
          }
        }

        /**
         * Refreshes the Memory-Information in the Statusbar (Swing-Threadsave).
         */
        public void refreshMemoryStatus() {
          SwingUtilities.invokeLater(memoryRefresher);
        }

        private Runnable memoryRefresher = new Runnable() {
          MessageFormat msgFmt = new MessageFormat("{0} of {1} MB used");

          @Override public void run() {
            long total = Runtime.getRuntime().totalMemory();
            memoryLabel.setText(msgFmt.format(new Object[]{(total - Runtime.getRuntime().freeMemory()) / 1048576L, total / 1048576L}));
          }
        };


        private void createScene() {

          Platform.runLater(new Runnable() {
            @Override public void run() {

              WebView view = new WebView();
              engine = view.getEngine();

              engine.titleProperty().addListener(new ChangeListener<String>() {
                @Override public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
                  SwingUtilities.invokeLater(new Runnable() {
                    @Override public void run() {
                      SimpleSwingBrowser.this.setTitle(newValue);
                    }
                  });
                }
              });

              engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
                @Override public void handle(final WebEvent<String> event) {
                  SwingUtilities.invokeLater(new Runnable() {
                    @Override public void run() {
                      lblStatus.setText(event.getData());
                    }
                  });
                }
              });

              engine.locationProperty().addListener(new ChangeListener<String>() {
                @Override public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
                  SwingUtilities.invokeLater(new Runnable() {
                    @Override public void run() {
                      txtURL.setText(newValue);
                    }
                  });
                }
              });

              engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
                @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
                  SwingUtilities.invokeLater(new Runnable() {
                    @Override public void run() {
                      progressBar.setValue(newValue.intValue());
                    }
                  });
                }
              });

              engine.getLoadWorker().exceptionProperty().addListener(new ChangeListener<Throwable>() {

                @Override public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
                  if (engine.getLoadWorker().getState() == FAILED){
                    if (old != null) old.printStackTrace();
                    if (value != null) value.printStackTrace();
                    SwingUtilities.invokeLater(new Runnable() {
                      @Override public void run() {
                        JOptionPane.showMessageDialog(panel, (value != null) ? engine.getLocation() + "\n" + value.getMessage() : engine.getLocation() + "\nUnexpected error.", "Loading error...", JOptionPane.ERROR_MESSAGE);
                      }
                    });
                  }
                }
              });

              engine.setOnAlert(new EventHandler<WebEvent<String>>() {
                @Override public void handle(WebEvent<String> event) {
                  System.err.println(event.getData());
      // MessageDialog.showMessageDialog(SimpleSwingBrowser.this, event.getData(), "Alert", MessageDialog.WARNING_MESSAGE);
                }
              });
              engine.setOnError(new EventHandler<WebErrorEvent>() {
                @Override public void handle(WebErrorEvent event) {
                  System.err.println(event.getMessage());
                  event.getException().printStackTrace();

      // DialogExceptionHandler deh = new DialogExceptionHandler();
      // if (event.getException() instanceof Exception){
      // deh.handleException(event.getMessage(), (Exception)event.getException(), new ExceptionContext(new Object[]{DialogExceptionHandler.CONTEXT_DIALOG_PARENT, SimpleSwingBrowser.this}));
      // }
                }
              });


              jfxPanel.setScene(new Scene(view));
            }
          });
        }


        public void goBack(){
          Platform.runLater(new Runnable() {
            @Override public void run() {
              final WebHistory history=engine.getHistory();
              ObservableList<WebHistory.Entry> entryList=history.getEntries();
              int currentIndex=history.getCurrentIndex();
      // Out("currentIndex = "+currentIndex);
      // Out(entryList.toString().replace("],","]\n"));

              String url = entryList.get(currentIndex>0?currentIndex-1:currentIndex).getUrl();
              history.go(-1);
              txtURL.setText(url);
            }
          });
        }

        public void goForward() {
          Platform.runLater(new Runnable() {
            @Override public void run() {
              final WebHistory history=engine.getHistory();
              ObservableList<WebHistory.Entry> entryList=history.getEntries();
              int currentIndex=history.getCurrentIndex();
              // Out("currentIndex = "+currentIndex);
              // Out(entryList.toString().replace("],","]\n"));

              String url = entryList.get(currentIndex<entryList.size()-1?currentIndex+1:currentIndex).getUrl();
              history.go(1);
              txtURL.setText(url);
            }
          });
        }

        public void loadURL(final String url) {
          Platform.runLater(new Runnable() {
            @Override public void run() {
              String tmp = toURL(url);

              if (tmp == null){
                tmp = toURL("http://" + url);
              }

              engine.load(tmp);

              //perform script calls like so:
      // engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
      // if (newValue == Worker.State.SUCCEEDED) {
      // // engine.executeScript("someJSFunctionCall('" + argument + "')");
      // }});
            }
          });
        }

        private static String toURL(String str) {
          try{
            return new URL(str).toExternalForm();
          }catch(MalformedURLException exception){
            return null;
          }
        }

        public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {

            @Override public void run() {
              SimpleSwingBrowser browser = new SimpleSwingBrowser();
              browser.setVisible(true);
              browser.loadURL("http://oracle.com");
            }
          });
        }
      }

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

      Attachments

        Issue Links

          Activity

            People

              mbilla Murali Billa
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: