JDK-8116651 : EXCEPTION_ACCESS_VIOLATION in jfxwebkit.dll when doing JSObject.toString when JSObject is passed through Event.getTarget in EventListener
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: 7u6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2012-08-09
  • Updated: 2015-12-02
  • Resolved: 2012-09-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Blocks :  
Relates :  
Description
I'm gettings these strange crashes in jfxwebkit.dll when I do a JSObject/Node toString. The strange thing is that some JSObject handle toString without problem, these JSObject are referenced from JSObject doc= (JSObject) WebEngine.getDocument(). Nodes that are accessed from a DOM event listener crash and burn when you touch them, except when you reference the Document object.

To reproduce create an empty ViewPart (http://efxclipse.org/tut3.html) and place the following snippets in the public void createPartControl(Composite parent) {} method.

>> Situation 1, content loaded from network..
public void createPartControl(Composite parent) {
        FXCanvas canvas= new FXCanvas(parent, SWT.NONE);
        WebView view= new WebView();
        canvas.setScene(new Scene(view));
        final EventListener insert_listener= new EventListener() {
            @Override
            public void handleEvent(Event event) {
                Node inserted_node= (Node) event.getTarget();

                // This prints [object HTMLDocument]
                System.out.println("inserted_node.getOwnerDocument() - " + inserted_node.getOwnerDocument());
                   
                // This crashes the JVM
                System.out.println("inserted_node - " + inserted_node);
            }
        };
        view.getEngine().documentProperty().addListener(new ChangeListener<Document>() {
            @Override
            public void changed(ObservableValue<? extends Document> observable,
                    Document oldValue, Document newValue) {
                if (oldValue instanceof EventTarget)
                    ((EventTarget) oldValue).removeEventListener("DOMNodeInserted", insert_listener, false);
                if (newValue instanceof EventTarget)
                    ((EventTarget) newValue).addEventListener("DOMNodeInserted", insert_listener, false);
            }
        });
        view.getEngine().load("http://google.com");
    }

>> Situation 2, content loaded from string..
    public void createPartControl(Composite parent) {
        String html= "<html><head></head><body><h1 id=\"foo\">Hello world</h1></body></html>";
        FXCanvas canvas= new FXCanvas(parent, SWT.NONE);
        WebView view= new WebView();
        canvas.setScene(new Scene(view));
        final EventListener click_listener= new EventListener() {
            @Override
            public void handleEvent(Event event) {
                Node clicked_node= (Node) event.getTarget();

                // This prints [object HTMLDocument]
                System.out.println("clicked_node.getOwnerDocument() - " + clicked_node.getOwnerDocument());
                   
                // This crashes the JVM (Click on the <h1> element)
                System.out.println("clicked_node - " + clicked_node);
            }
        };       
        view.getEngine().documentProperty().addListener(new ChangeListener<Document>() {
            @Override
            public void changed(ObservableValue<? extends Document> observable,
                    Document oldValue, Document newValue) {
                if (oldValue instanceof EventTarget)
                    ((EventTarget) oldValue).removeEventListener("click", click_listener, false);
                if (newValue instanceof EventTarget)
                    ((EventTarget) newValue).addEventListener("click", click_listener, false);
            }
        });
        view.getEngine().loadContent(html);
    }

See attachment for crash reports.
Comments
Verified with Lombard b91 on Win7x64.
30-05-2013

Yes, see RT-27876.
11-02-2013

Is there a fix or workaround for this bug in 2.2.x release line? See the question on the openjfx-dev mailing list: http://mail.openjdk.java.net/pipermail/openjfx-dev/2012-October/004043.html
24-10-2012

Final fix version: http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-24142/4 Changes: rt-closed/javafx-ui-webnode/src/com/sun/webpane/webkit/JSObject.java Now [peer] is a pointer to C++ object and could be - JSObject (can be used in context only, root JS restored by common procedure found in MAC port) - Node or Node child - DOMWindow Last two have a weak ref to JSObject , that is used/restored on each call. webnode/Source/WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp Fixed the problem with in-context Java object creation webnode/Source/WebCore/platform/java/BridgeUtils.cpp The check if (env->IsInstanceOf(val, clNode)) after if (env->IsInstanceOf(val, clJSObject)) is useless. We need JSContext, not JSGlobalContex for the most of case, that simplify the task. The MAC implementation: Source/WebCore/bridge/jni/jni_jsobject.mm is a good example of caching and encapsulation.
17-09-2012

While the latest merge with the Webkit trunk we got a new JS GC, that have a faster recycling procedure. The connection between DOM (C++ - WebCore) and JS (JIT - JavascriptCore) is weak. To say a long story short: we are trying to use cached JS object that was recycled by GC. The link between DOM and JS object could be broken at any time, so we need to check-and-restore JS wrapper on each call to DOM as JS object. Suggested fix: http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-24142/1
10-09-2012

Here is a problem with transformation from C++ to JS object. The problem is hard and need to be researched. Quick and easy solution is in limitation of DOM object calls by interface methods. The crash happen in toString method of JSObject that is currently afunctional.
06-09-2012

Any idea when to expect this fix to be available for the general public?
16-08-2012

Updated to JRE version: 7.0_06-b23. Same behavior. # # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x03a6883e, pid=3400, tid=3552 # # JRE version: 7.0_06-b23 # Java VM: Java HotSpot(TM) Client VM (23.2-b09 mixed mode, sharing windows-x86 ) # Problematic frame: # C [jfxwebkit.dll+0x2883e] Java_com_sun_webpane_webkit_dom_EventListenerImpl_twkDispatchEvent+0xc82e # # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows # # An error report file with more information is saved as: # C:\Dropbox\workspaces\HelloWorldJavaFX\HelloWorld\hs_err_pid3400.log # # If you would like to submit a bug report, please visit: # http://bugreport.sun.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. #
10-08-2012

This is the error report for the Hello world application
10-08-2012

Adjusted the Hello world sample from.. http://docs.oracle.com/javafx/2/get_started/hello_world.htm If you run the following program and click the text "Click here to crash JVM" the following message is displayed.. # # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x03a6883e, pid=1580, tid=3088 # # JRE version: 7.0_06-b22 # Java VM: Java HotSpot(TM) Client VM (23.2-b09 mixed mode, sharing windows-x86 ) # Problematic frame: # C [jfxwebkit.dll+0x2883e] Java_com_sun_webpane_webkit_dom_EventListenerImpl_twkDispatchEvent+0xc82e # # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows # # An error report file with more information is saved as: # C:\Dropbox\workspaces\HelloWorldJavaFX\HelloWorld\hs_err_pid1580.log # # If you would like to submit a bug report, please visit: # http://bugreport.sun.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # package helloworld; import org.w3c.dom.*; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.scene.web.WebView; import javafx.stage.Stage; public class HelloWorld extends Application { public static void main(String[] args) { launch(args); } @Override public void start(final Stage primaryStage) { primaryStage.setTitle("Hello World!"); final String html= "<html><head></head><body><h1 id=\"foo\">Click here to crash JVM</h1></body></html>"; final EventListener click_listener= new EventListener() { @Override public void handleEvent(final Event event) { javafx.application.Platform.runLater(new Runnable() { @Override public void run() { Node clicked_node= (Node) event.getTarget(); // This prints [object HTMLDocument] System.out.println("clicked_node.getOwnerDocument() - " + clicked_node.getOwnerDocument()); // This crashes the JVM (Click on the <h1> element) System.out.println("clicked_node - " + clicked_node); } }); } }; WebView webView= new WebView(); webView.getEngine().documentProperty().addListener(new ChangeListener<Document>() { public void changed(ObservableValue<? extends Document> observable, Document oldValue, Document newValue) { if (oldValue instanceof EventTarget) ((EventTarget) oldValue).removeEventListener("click", click_listener, false); if (newValue instanceof EventTarget) ((EventTarget) newValue).addEventListener("click", click_listener, false); } }); StackPane root = new StackPane(); root.getChildren().add(webView); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); webView.getEngine().loadContent(html); } }
10-08-2012

Tried the following code, same behavior, same crash final EventListener click_listener= new EventListener() { @Override public void handleEvent(final Event event) { javafx.application.Platform.runLater(new Runnable() { @Override public void run() { Node clicked_node= (Node) event.getTarget(); System.out.println(clicked_node); } }); } }; And the same goes for this.. final EventListener click_listener= new EventListener() { @Override public void handleEvent(final Event event) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { Node clicked_node= (Node) event.getTarget(); System.out.println(clicked_node); } }); } };
10-08-2012

Please make sure you always access JSObjects from FX thread. Is it possible that in the second scenario, EventListener is called on some other thread? That could be the reason.
10-08-2012

This crashes the JVM.. public void createPartControl(Composite parent) { String html= "<html><head></head><body><h1 id=\"foo\">Hello world</h1></body></html>"; FXCanvas canvas= new FXCanvas(parent, SWT.NONE); final WebView view= new WebView(); canvas.setScene(new Scene(view)); final EventListener click_listener= new EventListener() { @Override public void handleEvent(Event event) { Node clicked_node= (Node) event.getTarget(); JSObject document= (JSObject) clicked_node.getOwnerDocument(); JSObject foo= (JSObject) document.call("getElementById", "foo"); // This crashes the JVM (Click on the <h1> element) System.out.println("foo=" + foo); } }; view.getEngine().documentProperty().addListener(new ChangeListener<Document>() { @Override public void changed(ObservableValue<? extends Document> observable, Document oldValue, Document newValue) { if (oldValue instanceof EventTarget) ((EventTarget) oldValue).removeEventListener("click", click_listener, false); if (newValue instanceof EventTarget) ((EventTarget) newValue).addEventListener("click", click_listener, false); } }); view.getEngine().loadContent(html); }
09-08-2012

This runs fine... public void createPartControl(Composite parent) { String html= "<html><head></head><body><h1 id=\"foo\">Hello world</h1></body></html>"; FXCanvas canvas= new FXCanvas(parent, SWT.NONE); final WebView view= new WebView(); canvas.setScene(new Scene(view)); view.getEngine().documentProperty().addListener(new ChangeListener<Document>() { @Override public void changed(ObservableValue<? extends Document> observable, Document oldValue, Document newValue) { if (newValue instanceof EventTarget) { JSObject document= (JSObject) view.getEngine().getDocument(); JSObject foo= (JSObject) document.call("getElementById", "foo"); // prints foo=[object HTMLHeadingElement], does not crash System.out.println("foo=" + foo); } } }); view.getEngine().loadContent(html); }
09-08-2012