I used Java a lot when I was studying CS in college but I must have been asleep for the non coding stuff because I have a number of knowledge gaps. For example, I don’t know how to create a jar by hand. In my defense, it’s just so easy to use your IDE or a Maven plugin and 60% of the time it works every time – but really, it always works.
Right now I’m trying to spend more time getting back to basics and today I’m taking a closer look at jars. The ability to quickly build and execute a little utility jar is especially useful when you are working with containers and want to hit internal endpoints or if you are trying to find a way to reduce latency.
There are so many tutorials out there on how to do this but I kept getting stuck on this error:
Could not find or load main class your.package.Foo
As usual, Stack Overflow to the rescue (thanks Ramjet!). It turns out I was overcomplicating things by using a package and the corresponding nested directory that comes with it. Below are instructions for creating a JAR two ways – one without a package, and one with.
Creating a JAR the Old Fashioned Way
Here’s my app. It’s a basic little daemon that prints “Hello World” every 2 seconds. This is all you really need. No package, no complicated directory structure, no Java project in your IDE, just this.
HelloWorld.java
public class HelloWorld { public static void main(final String[] args) { while (true) { try { System.out.println("Hello World"); Thread.sleep(2000); } catch (Exception e) { break; } } } }
First I compile from the same directory as HelloWorld.java:
javac HelloWorld.java
This creates a corresponding class file:
$ ls HelloWorld.class HelloWorld.java
In the same directory create a manifest file. According to Oracle, “The manifest is a special file that can contain information about the files packaged in a JAR file.” This is important to us because it’s how the application’s entry point is defined.
manifest.txt
Main-Class: HelloWorld
*Note: make sure you have that new line at the end of the file! It will not work if this is missing.
Now create the jar.
$ jar cfmv HelloWorld.jar manifest.txt HelloWorld.class added manifest adding: HelloWorld.class(in = 588) (out= 398)(deflated 32%)
The “cfmv” part stands for:
c: create
f: send the output to a file instead of stdout
m: use an existing manifest file
v: verbose output
For more detail, see the Oracle JAR file tutorial
Finally, test the jar:
java -jar HelloWorld.jar Hello, World
It works!
Now if you are like me and really need to complicate things by using a package, or you didn’t know it packages were optional (err.. this is also me), here are alternate instructions:
Creating a JAR the Old Fashioned Way – With a Package
The app is the nearly the same as the earlier example. The only difference is it lives in the com.test.helloworld package which translates to the relative directory com/test/helloworld.
com/test/helloworld/HelloWorld.java
package com.test.helloworld; public class HelloWorld { public static void main(final String[] args) { while (true) { try { System.out.println("Hello World"); Thread.sleep(2000); } catch (Exception e) { break; } } } }
Compile from the same directory as HelloWorld.java:
javac HelloWorld.java
This creates a corresponding class file:
$ ls HelloWorld.class HelloWorld.java
In the same directory create the manifest file.
manifest.txt
Main-Class: com.test.helloworld.HelloWorld
*Note: make sure you have that new line at the end of the file! It will not work if this is missing.
Now navigate up to the root directory and create the jar. This is the tip I got off of SO. I’ll be honest I don’t know why I have to go back to the root directory but it’s the only thing that seems to work. It must have something to do with the package structure.
$ jar cfmv HelloWorld.jar com/test/helloworld/manifest.txt com/test/helloworld/HelloWorld.class added manifest adding: com/test/helloworld/HelloWorld.class(in = 623) (out= 420)(deflated 32%)
Now test the jar:
java -jar HelloWorld.jar Hello, World
It also works!
Pingback: itemprop="name">Connecting VisualVM to a Local Docker Container From Scratch – ${SITE_TITLE}