Pitfalls of multithreaded browser development

From Trephine

Jump to: navigation, search
« Site improvements - reducing dependencies Trephine worker threads made easy »

[subscribe] Recent blog entries

Live Demos

Pitfalls of multithreaded browser development

Browsers may be single threaded, but the broader spectrum of web technologies includes systems that are not. Understanding the effects of the browser threading model is crucial to developing safe cross-technology applications.

This article focuses on the effects of threading with regards to the intercommunication of Java and JavaScript via a technology called LiveConnect, specifically as it relates to trephine. Similar conclusions may be appliciable to other rich technologies such as Flash, Silverlight, Google's Native Client or custom browser plugins and extensions.

As a refresher, recall that LiveConnect allows browser JavaScript to call into Java applet methods via code such as this:

var applet = document.getElementById('some_applet_id');
var result = applet.someMethod("parameter", "list");
alert( "The result is " + result );

When the browser's JavaScript execution thread gets to the second line above, where it must call the applet.someMethod(), it locks up, waiting for the Java thread's response. That is, the call occurs synchronously, and no other DOM code will execute until it has finished.

Normally this is no trouble at all, but consider if the Java code attempts to call back into the DOM:

import netscape.javascript.JSObject;
import java.applet.Applet;
class MyApplet extends Applet {
    public String someMethod( String param, String list ) {
        JSObject window = JSObject.getWindow( this );
        Object result = window.eval( "/* JavaScript code here */" );
        return (String) result;
    }
};

In the above Java code, the result from someMethod() relies on the successful execution of JavaScript code via window.eval. But since the browser is still waiting for the result of the Java code, the two systems deadlock. That is, both are waiting for results from the other and the only way out is to kill the browser process and start over (bad news bears).

Using trephine, it is exceedingly simple to create this situation:

trephine.js( function() {
    window.eval( "alert('deadlocks ahoy!');" );
} );

From the above example, it may seem that it's impossible to call into the browser JavaScript environment from Rhino/trephine JavaScript. Fortunately threads are here to rescue us. By introducing an anonymous worker thread, we can ensure that the Java method called from the main thread finishes quickly, and later on makes its mark on the DOM.

trephine.js( function() {
    var thread = new java.lang.Thread(
        new java.lang.Runnable({
            run: function() {
                window.eval( "alert('cant touch this');" );
            }
        })
    );
    thread.start();
    return true;
} );

The reason this succeeds is that the anonymous worker thread can afford to wait for the browser's JavaScript execution thread to finish without blocking anything else. Of course, the above nomenclature is a little verbose considering how frequently this kind of intercommunication is likely to come up during development. In a future article, we'll explore ways of making this procedure as painless as possible.

As always, I look forward to your questions and comments!

--Jim R. Wilson (jimbojw) 01:14, 22 April 2009 (UTC)
Personal tools