When Java was introduced to an incredible reception in 1995 — I had just come to California — Sun was the king of the Unix systems manufacturers. While there were still others like HP, IBM and Silicon Graphics, Sun had the momentum: Sun pioneered “open systems”, it open-sourced even its chip designs, and it had a lot of credibility because it had people like Bill Joy who wrote a lot of the software stack that made Unix and Linux what it is today.
I was always very puzzled that somehow, the Java guys at Sun never seemed to talk to the SunOS / Solaris, operating system guys. Of course, Java’s entire mantra was “write once, run everywhere” and so they were minimizing operating system dependencies as much as possible, but that doesn’t mean they couldn’t have applied some useful principles.
Case in point: modules.
In most other programming languages — certainly C, and since then, languages like PHP, Perl, Ruby, Node, Python — things work like this:
- Your program consists of some parts you wrote, and some modules that other people wrote. Things like XML parsers, or database drivers, or math libraries that are useful not just to your program, but to many others as well. libc is the prototypical example.
- When you distribute your program, you distribute your program as a module, which has module dependencies on other people’s code which stay separate. Depending on language, that might be a different shared library, or Perl package, or Python egg or so forth.
- Depending on the operating system on which you deploy, you pick which of those modules you ship with your program, and which ones you expect the operating system to provide (or which the system administrator can easily install) so you don’t need to ship them to the customer yourself.
- That’s usually implemented by means of some kind of module search path. In Perl, for example, the default include path
@INC
might include/usr/lib/perl/site_perl:<current directory>
, which means “first look what the system has already, and then look for what’s bundled with the app”
But not so in Java. Java applications are usually shipped in gigantonormous JAR or WAR files — those are zip files that contain every single piece of code, and every single library the application might conceivably use, all at the same time. While I don’t deny that there are cases where that is the right approach, in many cases it’s not:
- Every time you update the application, you need to ship 10’s or 100’s of megabytes around. Even if it is just a typo.
- Every time you rebuild the application, you compress a big file, and every time the server updates it, it needs to uncompress again.
- If you run several apps on the same server, each of them might bundle the exact same libraries. Why not put them in a place on the server where several apps all can use the same module, as everybody else does?
- Dynamic modules are largely impossible: few Java applications have a plug-in architecture so third parties can add extensions, while I can’t think of any PHP app right now that doesn’t. Think of a WordPress with its thousands of third party modules written in Java: it would never have been possible.
So, I’d like this to be different, and in particularly I’d like this to be different on my personal server Linux distro: UBOS. So I’m proud to announce diet4j, a new open-source project that can run Java applications from a collection of independent modules, just like PHP and Python and those other guys can. diet4j is available already on diet4j.org in version 0.7, and will be available on UBOS shortly.
diet4j reuses the metadata of the Maven build system, which already encourages developers to build their applications as modules. And it does this in a way so that most Maven modules can already be used with diet4j without any change or recompile necessary.
There are some examples on the diet4j home page on how it works for Java apps started on the command-line, and Java web apps on Tomcat.
Better late than never to turn Java into a full-fledged Linux citizen :-)
P.S. Help wanted.