Applet Archaeology: races and waves

Here at Leaning Technologies we specialise in compilers: tools that are useful for software developers and enterprises, but rarely end up in the hands of end-users. Interestingly though, we happen to have an exception to this rule: our CheerpJ Applet Runner.

CheerpJ Applet Runner is a (free) Chrome extension which makes it possible to run legacy Java Applets on modern browsers, without requiring plug-ins or a local installation of Java.This is achieved by on-the-fly converting and running the Applets all within the browser, and not via some ugly remote execution / terminalisation trick.

We released this extension around 2 years ago, mostly as demo of our CheerpJ Java-to-JavaScript compiler. We were definitely not expecting it to be used very much and to be found useful in and of itself. I think that myself, and many fellow developers, suffer from an heavy modernity bias and we often fail to realise how much real people actually depend on outdated technologies.

I believe that Java Applets are a perfect example of this: they are universally reviled for their horrible security and usability, but still, the Internet is full of good quality, Java Applet content that people still need. Modern browsers dropped support for plug-ins, including Java) for very good security reasons, but this step forward has actually left some people behind out there.

For these people, the CheerpJ Applet Runner proved to be a good, easy-to-use solution, to our initial surprise. This lead to the CheerpJ Applet Runner to gain traction and be installed by up to 15,000 people! Whoop.

A big chunk of our users are students and teachers from all over the world, from developing countries to the United States. Java Applets have been for a long time extremely popular to make animated and interactive teaching material, especially for Physics and to a lesser extent Maths and Chemistry. For these student using our extension may be the only option to access these contents.

How do we know that students use our extension so much? Well, mostly from the bug reports we receive (more on this later), but we can also observe a very strong seasonal pattern in our install base.

Between May and June the school season ends. Correlation does not imply causation… but it gives you a hint.

Perhaps surprisingly, there are a lot of tricky details in the way applets are integrated and interact with a web page, so our extension included since the beginning a simple bug reporting interface to gather non-working samples from the wild.

Our bug report interface. Originally we also included a “bug description” field here, but nobody seemed to be able to provide useful information there. So we removed it altogether.

We receive a steady stream of around 1 bug report every 1 or 2 weeks, most of them about known, general issues, that we couldn’t fix yet. But every now and then we get more peculiar samples, like the following one:

A single applet is used to display multiple animations. The “Animation X” buttons will change the animation parameters using a JavaScript snippet (see below).

This is a pretty typical example of the legacy content which is enabled by CheerpJ Applet Runner. Aesthetically not very pleasing, but gets the job done. In this case it’s a collection of simulations about wave propagation and the Doppler effect.

The various JavaScript snippets that sets the animation parameters for the applet.

This page uses one Java Applet to display different animations, and there are five JavaScript functions which are used to change the contents. One of the capabilities of Java Applets was that all the public functions of the instance could be called directly from JavaScript. Yes, you could invoke arbitrary Java code directly from JavaScript at the time.

As you can see at the bottom of the screenshot the initial state is set-up directly using the page onload callback. Quite a lot of stuff has to happen for that code to be valid though:

  • To expose the Java methods the applet instance must be constructed
  • Which means that its code and all its dependencies must be downloaded and compiled
  • Which means that an arbitrary number of JAR and Java class files have to be downloaded over HTTP

All this should be asynchronous in the JavaScript programming model, but I think that originally the Java plug-in would block the whole browser execution during loading, so that by the time onload was executed the Applet would have been fully initialized.

This is fundamentally problematic for the CheerpJ Applet Runner, as it is subject to the normal limitations of code running in the main thread, in particular it cannot block waiting for data to be downloaded over HTTP.

To work around this problem CheerpJ Applet Runner has for quite some time manually detached the onload event handler from the body when one or more applets are detected in the page. The handler is then executed when all applet objects have been constructed. This solution has served us well so far, but was not enough for this specific case.

This page is calling some methods which actually require a full initialization of the internal state of the applet. That happens during it’s normal life cycle (i.e. the init and start methods), well after the constructor is run. I suspect that this code was actually also broken with native Java, as there is a race condition here. It could be that when the applet was written Java was already running JIT compiled code, while JavaScript was still only interpreted. If that was the case the Java side would always have been fast enough.

Even if the Applet was probably broken to begin with, I feel that we should do what we can to help people access the content they need, even if it’s poorly implemented. So we have amended our implementation to delay the onload callback after the init and start. This is an hack, but it seems to cause no regressions over our test suite of real world Applets, so it’s probably OK.

This page is now properly working in all its 2004 glory. Enjoy!

Get in touch

For more information on CheerpJ, check out our website at Follow us on twitter (@leaningtech), visit our website, or drop us a line on Gitter!


Leaning Technologies' Blog - everything Cheerp, CheerpJ…