The Decline and Fall of Java on the Desktop Part 1 (1999-2005)
Java was originally touted as "the killer" desktop language, but the early 2000's saw steady march towards obscurity.
This is the first in a series of articles about the history of Java on the Desktop, from my perspective as a developer who started working with Java in the late ‘90’s. I’m writing this, partly as a background for why I created jDeploy, a developer-friendly desktop deployment tool for Java. Despite the ominous tone of this article’s title, I believe that Java is a compelling platform for modern desktop applications. Stick around for the whole series to find out why.
Java was the official language of choice for teaching computing science when I was in university in the late ‘90’s through early ‘00’s. There were a few courses that required us to use C and C++, but all of the fundamentals were taught in Java. For the pedantic reader, I should also clarify that they were taught in Java, as opposed to just taught Java. In University Computing Science programs, they don’t actually teach particular programming languages. They teach concepts, and use programming languages to demonstrate those concepts. As a student, you’re expected to learn the programming languages on your own time. Some courses had hard requirements, like “This assignment must be done in Java”, but, for the most part, and especially in upper-level courses, you were free to do assignments in whatever language you felt comfortable with1.
When I entered University, my exposure to Java had been limited to Applets, and I didn’t have enough experience to know Java’s place in the world or what it improved over the technologies that came before it. However, I did have a sense that we were being ripped-off somehow - that it was just a toy language, and all “real” development was done in languages like C++. There was always some guy in the back-row of the class with a trench coat and messy beard who let his feelings about the superiority of C++ be known.
Java is Slow
“Java is slow”, they would say, and anyone who had ever used a Java GUI application, or a webpage with an applet, would have no choice but to agree. The only desktop applications I remember from that era that were written in Java were development tools (ArgoUML, and NetBeans come to mind), and they were buggy and slow. Oh so slow. It felt like you were working in molasses, as there was a lag on everything from scrolling to opening menus.
Professors who were enamoured with Java’s potential would insist that, with its just-in-time compilation, Java was actually quite fast - and, “theoretically” would run just as fast (or faster) than C++ once a code path was compiled. But we weren’t buying it. As far as I was concerned, the emperor had no clothes.
Java apps aren’t “real” apps
Another thing that made Java feel “second class” was the fact that the apps we built weren’t native apps. After you had “built” your app you would end up with a bunch of .class files or, if you were “advanced”, a .jar file that could only be run if the computer had Java installed. I was jealous when my BCIT and college friends would show me their projects, and they would be proper, real-life executables that you could double-click, and they would run, just like a real professional application - complete with all of the expected menus at the top of the window or screen.
I remember asking one of my profs about the possibility of producing a native executable, and he responded with “why would you want to do that?”. “That would negate all of the cross-platform benefits of Java. Once you compile it to a native executable, it isn’t cross-platform anymore”.
He suggested that I look into Java WebStart, if I wanted to deploy my app as a desktop application. That would allow users of Mac and Windows to install my app more easily than if it were a native bundle. WebStart sounded interesting, but it still felt like I’d been offered a bowl of soup, when I was asking for steak. Even if WebStart would allow me to distribute my app, it still required the user to have Java installed. (Albeit, at this point in time, circa 2001, Java came preinstalled on most computers), and it would seem foreign to users who were used to being able to download just double-click it to open it.
Furthermore, after experimenting with a few WebStart apps, it was apparent that the result was mediocre at best. The apps were always slow to open as they would download the updates, and they didn’t quite integrate properly into the operating system. There was a feature that would allow you to save an alias for the app on your desktop, but it never worked very well.
I’m sure that there were third-party tools at the time that would allow you to package a Java app as a native executable, but I’m just as certain that they were expensive, and "windows-only”. I was briefly excited about GCJ, the GNU compiler for Java that claimed to be able to compile Java down to machine code, but it only worked with a subset of APIs and didn’t support Swing - so GUI was out unless you wanted to use a native GUI toolkit.
My conclusion, at the time, was that Java was a dead-end for desktop development, unless I wanted to deploy as an applet - and by that time, Applets were even getting tired, when compared to lighter, faster technologies like Flash.
Applets: The killer app
Even though this isn’t meant to be a comprehensive chronicle, any history of Java on the desktop should at least pay some attention to Applets: The killer app for Java.
Applets were groundbreaking in 1995 as they allowed you to have interactive 2D graphics and animation for the first time right inside a webpage. In the beginning (Java 1.0), the Java interpreter shipped as part of the browser, but it wasn’t long before the model changed to use the system’s installed Java runtime via a plugin.
Originally, all you needed to do to embed your applet was upload your .jar file (or .class files) to your web server, and add an
<applet> tag in your webpage. Unfortunately, this simplicity wouldn’t survive. As new versions of Java were released, and Internet Explorer entered the scene, the HTML code required to embed your applet became increasingly complex, with different tags used for different browsers and versions or Java. The
<applet> tag was advertised as the correct way to embed an applet in a “multi-browser” environment, but Internet Explorer used the
<object> tag and Mozilla used the
Now, instead of
<APPLET code="MyAppletClass.class" archive="Applet.jar, EJB.jar" width="600" height="500" > </APPLET>
You would have something like:
<OBJECT classid="clsid: 8AD9C840-044E-11D1-B3E9-00805F499D93" width="600" height="500"> <PARAM NAME=CODE VALUE=MyAppletClass.class> <PARAM NAME="archive" VALUE='Applet.jar, EJB.jar'> <PARAM TYPE="application/x-java-applet;version=1.5.0"> <PARAM NAME="scriptable" VALUE="false"> <PARAM NAME="cache-option" VALUE="Plugin"> <PARAM NAME="cache-archive" VALUE="Applet.jar, EJB.jar"> <COMMENT> <EMBED type="application/x-java-applet;version=1.5.0" CODE=MyAppletClass.class ARCHIVE="Applet.jar, EJB.jar" WIDTH="600" HEIGHT="500" scriptable="false"> <NOEMBED> </COMMENT> </NOEMBED>WebSphere Java Application/Applet Thin Client for Windows is required. </EMBED> </OBJECT>
By Java 1.3, the user experience for applets was so fraught that Applets were only practical in an institutional setting where the system administrators had complete control over the software installed on the clients. It was no longer a practical way to add simple interactivity into web pages.
By 2001, applets had pretty much run their course. Flash had supplanted it as the standard for browser-based interactive media, as it was simpler, lighter, faster, and had a better install base (I recall something like 99% of computers had it installed).
Applets, by this time, were also giving Java a bad name, as security exploits were regularly being published, that were publicized as “Java security exploits”. This gave the false impression that anything written in Java was a security threat, even though these “exploits” generally only applied to Applets. They would linger around for many years to come, but mostly as a legacy technology.
I never considered Applets to be a viable way to ship desktop applications, but they were a fun technology while they lasted.
GUI Toolkits: AWT, Swing, and SWT
By the time I started working with Java, its original GUI toolkit, AWT (Abstract Windowing Toolkit) was already considered old, and its new “lightweight” toolkit, named Swing was all the rage. To make a long story short, AWT was a “heavy-weight” toolkit, meaning that it provided an API for working with native widgets. The problem with a heavy-weight UI library is that it is difficult to maintain, and is limited by the components that are available in the underlying platforms. Swing, by contrast, was a light-weight toolkit, meaning that it draws all of its own widgets, which is much easier to maintain, and makes cross-platform interfaces much easier to build.
Swing had a pluggable UI so that it could be styled to mimic the look of the native platform. When run on a Mac, a Swing UI would look the same as a native Cocoa app. When run on Windows, it would look like Windows, etc…. It also allowed for custom look and feels that didn’t conform to any particular platform. It was very flexible.
On the computers of the early 2000’s, Swing interfaces were also notoriously laggy. NetBeans was almost unusable on my bondi-blue iMac 233MHz. It was more usable on my dad’s G4 400MHz, but still felt like steering a U-haul truck through a mini-golf course.
Building GUIs in Java, at the time, required large amounts of faith in the power of Moore’s law. It may be slow like molasses now, but just give it a couple of years.
One day, circa 2002, my room-mate introduced me to Eclipse, and SWT - an alternative for Java GUI development that seemed to solve the performance problems. Eclipse used (and still uses) SWT, the Standard Widget Toolkit, a new “heavy-weight” UI toolkit for Java. Eclipse (which was built using SWT) was demonstrably more responsive than NetBeans (which was built using Swing), so on its face, it looked like we had a clear winner.
Because SWT didn’t need to draw its own widgets, but rather just provided bindings for platform native widgets, apps built with it felt more native, and were quite a bit more responsive. Having read about AWT’s problems, I was a little bit wary. If the smart guys at Sun had concluded that lightweight was the way to go, then why did these upstarts at..err IBM.. think they could do better?
My excitement about SWT didn’t last, however. Eclipse, though faster and more responsive than NetBeans, still felt clunky to use. It didn’t quite feel native. And Swing, though slower, was improving with every release. Based on the number of books, forums, and blog posts on AWT and Swing, I estimate that the Swing community was much larger than SWT’s. Swing/AWT was (and is still) the only toolkit that is included as part of Java, so you can build a full GUI app without any 3rd-party dependencies, other than the Java runtime environment.
Although I still haven’t used SWT in a real project, I am comforted by the fact that it is there. Some alternative JVMs2 have sprung up over the years that don’t support Swing, and has been a quick means of writing GUI apps on such platforms.
As far as I know, in the early 2000’s AWT, Swing, and SWT were the only games in town for cross-platform Java GUI development. Java FX didn’t come along until 2007 (I’ll talk more about that in my next post).
Java Cocoa Apps
It was around that time that Apple publicly announced that they would be embracing Java as a first-class citizen on Mac OS X. Java would come preinstalled with OS X, and Swing would be given a Native Mac theme so that they would look and feel just like a native app. This meant that you could ship a Java app to Mac users and be confident that it would run, and look good.
They also provided tools for bundling Java apps as a native OS X .app, so that, for the first time, you could ship a Java app as an, honest-to-God, real native app. Your users wouldn’t even be aware that your app was written in Java if you followed the Mac User Interface guidelines closely enough.
Unfortunately most developers of Swing apps didn’t follow the Mac UI guidelines, so users could still feel that something was “off” when they used a Java app. Apps might use the wrong accelerator keys for menu items, or be missing standard menus altogether. In truth, it requires a lot of work to make a Swing UI feel fully native on Mac. Unlike the native Mac UI toolkit, Cocoa, which gives you a fully-native app shell, complete with menus, as a starting point, Swing apps start you at zero. You have to create your own windows and menus from scratch, unless you’re using a framework - and I still have never seen a Java framework that gives you a fully-native Mac app experience as a starting point.
But, not to fret - Apple went a step further and provided Java bindings for Cocoa, which meant that your Java app could not only look like a native app, it would actually be a native app. In this scenario, you would create a new Cocoa project in Xcode, and select Java as the language for the project. It would then give you that beautiful native app shell as a starting point. And when you pressed “Build”, it would produce a fully-native app that you could send to your users.
I wrote a few sample apps with this Cocoa bridge, and it was quite polished. However, it suffered from being the red-headed step-child. Such apps would be Mac-only because they used Mac’s beautiful, but proprietary, UI, so they were panned by the WORA zealots in the Java community. And the “native” mac development community wasn’t interested in using Java. Therefore documentation was scarce. If you wanted to use the Cocoa-Java bridge, you had to become adept at converting Objective-C code examples into their Java equivalents. This was never fun.
Not surprisingly, Apple retired the Cocoa-Java bridge after only a few years (in 2005). Apple’s interest in Java dissipated for various reasons. I recall a quote from Steve Jobs around that time that “Java is a giant ball and chain”. He wasn’t wrong.
If you’re interested in writing Cocoa apps in Java, the Rococoa project picked up the torch, and as far as I can tell, it is still active.
Where does that leave us?
This history is neither meant to be comprehensive, nor necessarily chronological. I’m recounting my own journey through the Java desktop landscape, and it will be biased towards Mac (since I have been a Mac since my Dad bought our family a Mac Classic - and an Apple user before that, with our family IIgs).
That said, we’re roughly circling around the year 2005, which, arguably was a turning point for Java on the desktop. Before 2005, there are lots of questions and answers in online forums about Java desktop technologies like Swing, Cocoa bridge, etc…. After 2005, there really isn’t much. What happened in the years leading up to 2005, or perhaps in 2005 specifically that caused this blackout? Where did all of the Java desktop developers go? Likely many of them moved to the server-side, and the ones who stayed on the client likely shifted their attention to the web, or to native development.
I’ll explore this exodus in greater detail, in my next instalment. Remember to subscribe to this newsletter so you won’t miss it.
Also please add your own perspectives about this history in the comments. We all experienced this period a little bit differently, and I’m interested to know what it looked like to devs who came from different backgrounds, or at a different stage in their career.
Part 2 of this series has been posted here.
Some assignments required the use of particular libraries or programming languages. E.g. I recall an Operating Systems assignment on threads that required the use of the pthreads library, and, thus required us to use C.