Martian Software, Inc. logo

Nailgun Background

Or, Making Java Practical for Command Line Utilities

The Java language is mistakenly perceived by many as slow. In reality, Java applications can perform extremely well - once they're already running. The startup time of the Java Virtual Machine (JVM) itself is at best aggravating, and at worst sufficient reason not to use Java to perform certain tasks. To Sun's credit, this has improved with each version of Java.

But it's still annoying, and as a result Java has found a niche in server-side applications that run for extended periods of time, rendering the JVM startup time irrelevant. Apache Tomcat is an example of an enormously successful Java-based server application.

It's a shame the JVM takes so long to launch - Java has an extensive and robust core API and huge number of available open source libraries. For better or for worse, it's a great big hammer, making almost any programming project look like a nail. Hence Nailgun.

The idea is simple: Run all your Java apps in the same JVM, the Nailgun server, which only needs to start once. Run a very thin client, written in C for speed, that sends your environment variables, command line, and a few other items to the Nailgun server using TCP. Once connected, send the client's stdin to the server, and send the server's stdout and stderr to the client's stdout and stderr. Trap System.exit() on the server, and have the client exit accordingly.

Of course, not all Java apps can be run this way. But simple, text-based programs are perfect for Nailgun - in fact, they end up running nearly as fast as their C counterparts. GUI programs work with Nailgun as well, although it can be confusing if the client and server are not on the same physical machine.

The Nailgun server is written in pure Java. The client has been tested on Linux, Windows, and OS X. So far, results have been excellent. Below is the timing information for a "Hello, world!" program run first through Java, then via Nailgun. The same .class file was used in both cases.

$ time java com.martiansoftware.nailgun.examples.HelloWorld Hello, world! real 0m0.132s user 0m0.080s sys 0m0.010s $ time ./ng com.martiansoftware.nailgun.examples.HelloWorld Hello, world! real 0m0.004s user 0m0.000s sys 0m0.000s

Note that the above example is a best-case scenario. A Java program that only prints "Hello, world!" is dominated by JVM startup time. Programs that run longer will still be faster in Nailgun, but there's a definite diminishing return the longer your programs run. There's no point at all in running something like Tomcat within Nailgun.

What is it good for?

I'm not sure yet. It's certainly excellent for simple command line utilities. But because the JVM keeps running, it can be used for other interesting things, such as simple inter-process communication between shell scripts. You can embed the Nailgun server in your own applications (the jar is < 30KB), then interact with your running application via the Nailgun client. Because the client and server can run on different machines, a client can trigger a process on a server and "pick up" the result later. I'd love to see an adapter for Ant to make builds a little faster...

In other words, consider this a platform for experiments. If you come up with any particularly clever ideas, please let me know!

Before you download it, be aware that *it's not secure*. Not even close. Although there are means to ensure that the client is connected to the server from the local machine, there is not yet any concept of a "user". Any programs that run in Nailgun are run with the same permissions as the server itself. You have been warned.

Credits

Special thanks to Pete Kirkham and Angsuman Chakraborty for making the Windows port of the Nailgun client possible. Pete also provided the code for trapping System.exit().

Thanks also to Adam Sherman for an amazing 30-minute turnaround on Mac testing following the initial release.