JDK-8185965 : JavaVM crashes when loading a certain WebPage inside JavaFx WebView
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: 8u131,9,10
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: x86
  • Submitted: 2017-08-08
  • Updated: 2020-01-31
  • Resolved: 2017-12-09
Related Reports
Duplicate :  
Duplicate :  
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 ----------


Comments
Tested after WebKit 605.1 (JDK-8187483) and this crash is not reproducible. Hence closing this issue as duplicate of JDK-8187483.
09-12-2017

Tested this issue on Linux and OS X with 9.0.3+9 (64 bit) and crash is not reproducible. Looks like this JIT crash is windows specific.
29-09-2017

Raising to P2 since we have a case where it crashes consistently.
26-09-2017

Debugging with Release build debug info and getting below exception at function JSValue JITCode::execute(VM* vm, ProtoCallFrame* protoCallFrame) in JITCode.cpp Unhandled exception at 0x000007FEC8798767 (jfxwebkit.dll) in java.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF. Below is the call stack; jfxwebkit.dll!JSC::JITCode::execute(JSC::VM * vm, JSC::ProtoCallFrame * protoCallFrame) Line 82 C++ Symbols loaded. jfxwebkit.dll!JSC::Interpreter::executeCall(JSC::ExecState * callFrame, JSC::JSObject * function, JSC::CallType callType, const JSC::CallData & callData, JSC::JSValue thisValue, const JSC::ArgList & args) Line 941 C++ Symbols loaded. jfxwebkit.dll!JSC::call(JSC::ExecState * exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData & callData, JSC::JSValue thisValue, const JSC::ArgList & args) Line 39 C++ Symbols loaded. jfxwebkit.dll!JSC::callGetter(JSC::ExecState * exec, JSC::JSValue base, JSC::JSValue getterSetter) Line 87 C++ Symbols loaded. jfxwebkit.dll!JSC::PropertySlot::functionGetter(JSC::ExecState * exec) Line 33 C++ Symbols loaded. [Inline Frame] jfxwebkit.dll!JSC::PropertySlot::getValue(JSC::ExecState *) Line 383 C++ Symbols loaded. [Inline Frame] jfxwebkit.dll!JSC::JSValue::get(JSC::ExecState *) Line 798 C++ Symbols loaded. jfxwebkit.dll!llint_slow_path_get_by_id(JSC::ExecState * exec, JSC::Instruction * pc) Line 657 C++ Symbols loaded. jfxwebkit.dll!llint_entry() Line 3876 Unknown Symbols loaded. [External Code] Annotated Frame jfxwebkit.dll!llint_entry() Line 3944 Unknown Symbols loaded. [External Code] Annotated Frame jfxwebkit.dll!llint_entry() Line 9380 Unknown Symbols loaded. [External Code] Annotated Frame
12-09-2017

Issue is reproducible from JDK 8u131 onwards. Last worked in 8u122. JVM crashes when JavaFX webview loads "http://live.yworks.com/demobrowser/index.html#Business-Process-Models" webpage. 8u122 : Pass 8u131 : Fail <--- Regression introduced here. 8u144 : Fail 9-ea+181 : Fail Crash doesn't produce any error on console or any hs_err log report file.
08-08-2017