rss

How to create executable JAR archives with dependent libraries

Wednesday, October 28, 2009

As you may know, you can combine several Java classes into a runnable JAR file. Through this approach you can pack large projects and execute them more easily.
The following steps will illustrate how to create and run a JAR file.

1. Create a JAR


First, you need to create a Manifest file, which should contain at least the following lines:

  • Class-Path: <lib1.jar> <lib2.jar> <path/lib3.jar>
  • Main-Class: <classname>
  • Place a new line at the end of this file

Then use jar.exe to create a runnable JAR using the following command:

jar cvfm <your_jar_file.jar> <manifest_file> 
                              <class_files> <libraries>

If you prefer, you can use a Ant script to generate the manifest and create the JAR file. Within this script you need to change the value for jar.name and main.class. Optionally you may need to adjust the values for build.home and deploy.home.

<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" default="jar">

  <!-- Name of the output .jar file -->
  <property name="jar.name" value="jar_name.jar" />

  <!-- Base directory for distribution target -->
  <property name="deploy.home" value="." />

  <!-- Base directory for compilation targets -->
  <property name="build.home" value="." />

  <!-- Main class -->
  <property name="main.class" value="my.path.to.the.main.Application" />
 
  <!-- The base directory for all libraries (jar) files -->
  <property name="lib.home" value="lib" />

  <target name="jar" description="Create jar and MANIFEST.MF">

    <pathconvert property="libs.project" pathsep=" ">
      <mapper>
        <chainedmapper>
          <!-- remove absolute path -->
          <flattenmapper />

          <!-- add lib/ prefix -->
          <globmapper from="*" to="lib/*" />
        </chainedmapper>
      </mapper>
      <path>
        <!-- lib.home contains all jar files, 
                                        in several subdirectories -->
        <fileset dir="${lib.home}">
          <include name="**/*.jar" />
        </fileset>
      </path>

    </pathconvert>

    <!-- create the jar -->
    <jar jarfile="${deploy.home}/${jar.name}" basedir="${build.home}/classes">

      <manifest>
        <attribute name="Built-By" value="${user.name}" />
        <attribute name="Main-Class" value="${main.class}" />

        <!-- Finally, use the generated libs path -->
        <attribute name="Class-Path" value="${libs.project}" />
      </manifest>

    </jar>
  </target>

</project>

As a result you may get something similar to:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 11.3-b02 (Sun Microsystems Inc.)
Built-By: bruno.simoes
Main-Class: my.path.to.the.main.Application
Class-Path: lib/somelib.jar lib/anotherlib.jar

2. Execute a JAR


Double click the .jar file and see what happens. Maybe it is already working, and you have to do nothing. If it opens in your archiver software, then you need to find out what OS are you running and then respectively associate the file with the Java Runtime Environment.

2.1 Windows
  1. Go to "My Computer", click on one of your drives (C for instance). When it is shown, choose "Tools->Folder Options" (or Properties. It's in different places depending on the windows version). Alternatively, open windows explorer (just open any folder) to get the "Tools -> Folder Options" window.
  2. When you get the folder options window, click on the tab "File Types". You should be able to either edit or add JAR files (.jar extension)
  3. Change the program used to open JAR files. In the file select window, go to the folder where the JRE is installed (should be C:/Program Files/Java/ (...), mark "Always Open With", and select the javaw.exe file

Another way to do it is:

  1. Left-click the .jar file, and select the option "Open With".
  2. If you can't see it in the left-click menu, try holding shift while clicking.
  3. Select javaw.exe as above, and see if it runs.

2.2 GNU/Linux
  1. In the left click menu, there should be the "open with" enabled by default. Select "Sun Java X.X runtime", and run it.
  2. If you want to always open .jar files with Java instead of the archiver, select the right click menu, click on properties.
    • Select the open with tab.
    • There should be the Java software there to select. Make your choice, and confirm.

2.3 Command Line
  1. Open a command line window.
    • In Windows, click on "start", select "run", and type "command" or "cmd" on the text box.
    • For GNU/Linux, I assume you know how to do it.
      • It really depends on the distribution you are using, but GNU/Linux users work much more with the command prompt.
      • you can press ctrl + alt + F1-F6 to switch to text console, and ctrl + alt + F7 to return to the graphic mode.
  2. Go to the folder with the .jar file.
  3. Type:

    java -jar <your_jar_file.jar>


7 comments:


Anonymous said...

I want to quote your post in my blog. It can?
And you et an account on Twitter?



Alp Yogurtcuoglu said...

Thank you so much :) Now I can make nice executable jar files :)

Cheers,

Alp



Bruno Simões said...

You are welcome!

Best Regards,
Bruno Simões



Javin @ hashtable example in java said...

great tutorial. I have also shared some tips around how to create executable jar in java and how to view contents of jar file. you may find interesting.



wookiebreath said...

I can't tell you how long I've searched for a meaningful example of adding 3rd party dependencies to the stinking Manifest file. Excellent work with the pathconvert - routine.



Anonymous said...

Thanks a lot for the above example. My problem is when the jar is created it is not having any .class file inside the jar, rather I can see .java files are created. As a result when I am using java -jar jar_name.jar, I am getting the following exception,
java.lang.ClassNotFoundException: main.com.action.MainClass.

Can you please suggest me what I am missing.



Bruno Simões said...

Hi, are you using the ant script ?

Probably you need to readjust the variable basedir="${build.home}/classes" to match the folder containing your *.class. Common alternatives are basedir="${build.home}/bin".

Best Regards,
B