Java: A platform for platforms
Sun's reorg may seem promising to shareholders but it's also a scramble for position. The question now is whether Sun can, or wants to, maintain its hold on Java technology. Especially with enterprise leaders like SpringSource and RedHat investing heavily in Java's future as a platform for platforms

Also see:

Discuss: Tim Bray on 'What Sun Should Do'

Featured Whitepapers
Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Java Tip 127: See JAR run

Enable your unrunnable JARs to run with the java -jar command

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
You can easily package an application's entire set of classes and resources into a Java Archive (JAR). In fact, that is one goal of having jar files. Another is to let users easily execute the application stored in the archive. Why then are jar files second-class citizens in the Java universe—functioning only as archives—when they can be first class, right alongside native executables?

To execute a jar file, you can use the java command's -jar option. For example, say you have a runnable jar file called myjar.jar. Because the file is runnable, you can execute it like this: java -jar myjar.jar.

Alternatively, the Java Runtime Environment (JRE), when installed on an OS like Microsoft Windows, associates jar files with the JVM so you can double-click on them to run the application. These JARs must be runnable.

The question is: How do you make a JAR runnable?

The manifest file and the Main-Class entry

Inside most JARs, a file called MANIFEST.MF is stored in a directory called META-INF. Inside that file, a special entry called Main-Class tells the java -jar command which class to execute.

The problem is that you must properly add this special entry to the manifest file yourself—it must go in a certain place and must have a certain format. However, some of us don't like editing configuration files.

Let the API do it for you

Since Java 1.2, a package called java.util.jar has let you work with jar files. (Note: It builds on the java.util.zip package.) Specifically, the jar package lets you easily manipulate that special manifest file via the Manifest class.

Let's write a program that uses this API. First, this program must know about three things:

  1. The JAR we wish to make runnable
  2. The main class we wish to execute (this class must exist inside the JAR)
  3. The name of a new JAR for our output, because we shouldn't simply overwrite files


Write the program

The above list will constitute our program's arguments. At this point, let's choose a suitable name for this application. How does MakeJarRunnable sound?

Check the arguments to main

Assume our main entry point is a standard main(String[]) method. We should first check the program arguments here:

    if (args.length != 3) {
        System.out.println("Usage: MakeJarRunnable "
                           + "<jar file> <Main-Class>
<output>");
        System.exit(0);
    }


Please pay attention to how the argument list is interpreted, as it is important for the following code. The argument order and contents are not set in stone; however, remember to modify the other code appropriately if you change them.

Access the JAR and its manifest file

First, we must create some objects that know about JAR and manifest files:

    //Create the JarInputStream object, and get its manifest
    JarInputStream jarIn = new JarInputStream(new FileInputStream(args[0]));
    Manifest manifest = jarIn.getManifest();
    if (manifest == null) {
        //This will happen if no manifest exists
        manifest = new Manifest();
    }


Set the Main-Class attribute

We put the Main-Class entry in the manifest file's main attributes section. Once we obtain this attribute set from the manifest object, we can set the appropriate main class. However, what if a Main-Class attribute already exists in the original JAR? This program simply prints a warning and exits. Perhaps we could add a command-line argument that tells the program to use the new value instead of the pre-existing one:

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources