Friends of OpenJDK Today

Migrating Browser-Based Java Applets to IcedTea-Web using JNLP

February 02, 2021


  • Avatar photo
    Holger Isenberg

    Holger Isenberg has done system operation and consulting around Java-based enterprise applications since 1999 in Germany and moved in 2016 to Silicon Valley now solving customer problems at Azul Systems ... Learn more

"Does it run on JDK 11?" -- That's an always interesting question!

As a practical, more challenging example around this question, I used a 20 year old JAR, once created for a Java Applet to be run in the Java 1.1 Browser Plugin. Yes, that's 1.1 not 11!

To cut to the chase for those who fear this may be too long to read: yes it runs! 🙂

And to provide more detail—it now runs outside of any Web Browser and without modifying its decades-old JAR. The Applet was once created and offered to browse through all raw color images uploaded by the Mars Pathfinder Lander which settled down on the planet on July 4th, 1997.

That's the same lander / rover combination which saved the day for Mark Watney in the 2015 movie ​The Martian​ and already before in the 2000 movie ​Red Planet​ for Robby Gallagher, where they were able to reuse its parts, telnet into the software and regain contact with Earth.

The need for having access to an old Java Applet sometimes feels like being in Mark Watney's situation -- when the Applet is the only remaining communication channel to a legacy storage array requesting admin input to continue the important migration work. Often, the elongated ultimate diamond support contract has expired decades ago and the vendor cannot be convinced to offer alternatives. The alternative to change the source is blocked by missing USB-C compatible floppy disk drives to import it or the backup tape coating with the CVS repository had disintegrated into oxide dust when picking it up.

Here the original Pathfinder Applet Page: ​ You can click on that page, but don't try to make it usable by installing any plugins or extension into your Web Browser, as that would introduce the unsafe and outdated Applet Plugin to your system!

Instead, use the recipe explained below to create a JNLP file so you can run the Applet on current OpenJDK 11 with IcedTea-Web independently from any Web Browser.


For those who consider this rocket science and just want to see the result after migration, the migrated Pathfinder application is accessible here: ​ For those who are curious about all the details, here is the general workflow with code:

The idea provided here utilizes the Applet-feature of Java Web Start which was integrated into the JNLP file format to help during the migration of Java Applets to standalone applications. With that feature, it is possible to run at least those Applets which don't interact much with the HTML page they are embedded into. Simple interaction though, like calling URLs over http or https still works. While the same name "Applet" is used in JNLP, it is technically a normal standalone application, not connected to any web browser.


To start, you first need to install OpenJDK 11 and IcedTea-Web on the desktop system where you like to run the Applet. Both are offered on various download locations. For example, you can get them from here:

IcedTea-Web also runs on OpenJDK 8, but I recommend to start first with JDK 11, even for decade-old Applets. After installation of both, the next step is to check details about the web page containing the Applet you want to migrate.

Locating the Applet in the HTML Page

Usually, an Applet is embedded in a single large web page using the <applet>, <object> or <embed> tag.

That page might be visible only after logging in with username and password into the application start page. Download the Applet-HTML page or look into it in the Browser HTML source/inspect view. The interesting section which needs to be copied as text should look similar to one of the following three examples listed below. Also write down the full URL of that Applet-HTML page. Sometimes several of the 3 tags are included to offer compatibility for different browsers, but the information in all of them should be the same.


This is the original method to include Applets.

    code="MyJavaClass.class" archive="myapp.jar" 
    width="600" height="400" > 
  <param name="param1" value="value1">
  <param name="param2" value="value2">
  <param name="param3" value="somedir/otherdir"> 
  Alternative text.


This was added later as an alternative to the Applet tag.

<object codetype="application/java" 
    classid="java:MyJavaClass.class" archive="myapp.jar" 
    width="600" height="400" 
    codebase="plugin/1.3/" >
  <param name="code" value="MyJavaClass.class"> 
  <param name="archive" value="myapp.jar"> 
  <param name="codebase" value=".">
  <param name="type"
  <param name="scriptable" value="true">
  <param name="param1" value="value1">
  <param name="param2" value="value2">
  <param name="param3" value="somedir/otherdir">
  Alternative text.


This was used by the Netscape Browser.

<embed type="application/x-java-applet;version=1.1" 
   code="MyAppClass.class" archive="myapp.jar"
   width="600" height="400"
   pluginspage="plugin/1.3/plugin-install.html" > 
   param1="value1" param2="value2" param3="somedir/otherdir"
  <noembed>Alternative text.</noembed> 

Creating a JNLP file

Based on the copied <applet>, <object> or <embed> section, create a JNLP file named myapp.jnlp here in this example. The content should look similar to the following, with all attributes, parameters and URLs replaced by the actual values from your application:

<?xml version="1.0" standalone="yes"?>
<jnlp spec="1.5+" xmlns="" codebase="" href="myapp.jnlp">
       <homepage href="https://mywebsite.domain"></homepage> 
       <offline-allowed />
       <j2se version="1.2+"></j2se>
       <jar href="http://mywebsite.domain/somepath/myapp.jar" main="true"></jar>
       <jar href="http://mywebsite.domain/somepath/mylib.jar"/>
      name="MyMainClass" main-class="MyMainClass"
      width="600" height="400">
     <param name="param1" value="value1"/>
     <param name="param2" value="value2"/>
     <param name="param3" value="somedir/otherdir"/>

I'm using an empty "codebase" attribute as for the first step the file will only be used locally. Because of the empty codebase, we then have to add the complete absolute URLs in the jar href attributes. Without this, IcedTea-Web would try to update the local JNLP file from the codebase URL, which will fail. We'll now try to run the newly created file on IcedTea-Web.

Running the Migrated Applet

To run the Applet now on IcedTea-Web, enter the following commands depending on the OS you use on your desktop system.

Linux / macOS: myapp.jnlp

Windows (open a command window / Powershell first):

javaws myapp.jnlp

I'm not using the javaws -Xoffline parameter as then IcedTea-Web won't download the application JARs. If you see a JAR no found error on this first start, try again as then IcedTea-Web will have filled the local JAR cache. Depending on the further outcome of these first tries, you might need to adjust the JNLP file, like fixing jar href URLs, changing application parameters or others. For some applications you might also need to add the -nosecurity parameter (javaws -nosecurity myapp.jnlp).

To see more detailed error messages and warnings, run the IcedTea-Web configuration tool:

Linux / macOS:



Then enable logging to the terminal at Debugging -> Enable debugging. Writing the logs to a file can also enabled there. The configuration tool also allows to wipe the local JAR cache which is helpful during implementing the solution: Cache -> View Files -> Purge

Placing the JNLP file on a Web Server

This step is not always needed and often not possible, but it allows for easier start of the migrated Applet. This step is about copying the JNLP file to a Web Server and add a link to it from the original Applet start page to help users to migrate away from the Plugin-based Applet.

To make the JNLP file usable from a web page, you need to enter the base URL of that web page into the codebase attribute of the JNLP file. If the web page URL is for example http://mywebsite.domain/somepath/page.html then the base URL is entered into the JNLP file as codebase="http://mywebsite.domain/somepath/".

Now, users can start the application with the following command. If the JNLP file is later updated on the web server, it will automatically be downloaded again in the background before starting the application.

Linux / macOS: http://mywebsite.domain/somepath/myapp.jnlp


javaws http://mywebsite.domain/somepath/myapp.jnlp

For security reasons I would refrain from registering the JNLP file type with the javaws application on the Operating System as it can be mis-used by malicious web sites and unaware users can be lured to click and download JNLP files and then get it executed locally on their system. Instead, storing a script or start menu entry with the complete javaws command as used above including the JNLP file or URL is often a good solution.


  • Avatar photo
    Holger Isenberg

    Holger Isenberg has done system operation and consulting around Java-based enterprise applications since 1999 in Germany and moved in 2016 to Silicon Valley now solving customer problems at Azul Systems ... Learn more

Comments (1)

Your email address will not be published. Required fields are marked *

Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.

Save my name, email, and website in this browser for the next time I comment.


When trying this on some old applets where the .jar file signature uses the now deprecated SHA1 or MD5: On those when running on current Java 8 or 11 versions since October 2022 you will most likely see the following error message:

Cannot grant permissions to unsigned jars. Application requested security permissions, but jars are not signed.

Verifying the JAR signature will provide more details about the root cause, i.e. which algorithm or method exactly is now disabled:

$ jarsigner -verify -verbose myapplet.jar

In most cases it is SHA-1 which then needs to be re-enabled for JAR signature verification by modifying file $JAVA_HOME/jre/lib/security/ and changing the line starting with jdk.jar.disabledAlgorithms by removing the entry about SHA1 (or MD5 in some cases).

But be aware that your JRE is now potentially exposed to security issues due to the re-enabled weak hash algorithms for verifying JARs. That JRE should now only be used to run trusted JARs.

More details about the change and the workaround:

Subscribe to foojay updates:
Copied to the clipboard