I’m recently learning about AWS features and one of them are “Lambdas”. Those are functions that can be deployed and triggered on various events (like HTTP request, or file upload), but you don’t have to maintain the servers that run them. By default AWS provides several runtimes like NodeJS, Python and Java. Since I’m recently a bit tired with Python, I’ve decided to refresh my Java knowledge. The first step would be to understand the Java manifest files.

What is Java Manifest?
While you can find some description of manifests in Oracle’s official docs, they don’t really seem to be something that gives you an idea, what it is:
When you create a JAR file, it automatically receives a default manifest file. There can be only one manifest file in an archive, and it always has the pathname.
Honestly? I didn’t have any clue what to do with that info. So what are manifests?
Well, think about it that way: when you compile java source code, you get binary class
files. Those files are understood by the Java Virtual Machine, which is something that actually runs it. Just as you type python main.py
to run Python script, you can execute those binaries by running javac Main.java
and then java Main.class
to compile and run Java source code (the link to the example repo is at the end of this article). The problem with this approach is that in big projects, you’re going to have tons of those class
files and you’d like to pack them into a single file that you can run.
Indeed, someone has thought about solving this problem and has designed the jar
files. Jars contain compressed code. You can create your jar by running jar cf Main.jar Main.class
. It creates Main.jar
out of the Main.class
file. Cool. Let’s run it.
$ java -jar Main.jar no main manifest attribute, in Main.jar
Why Doesn’t My jar Work?
As you can see there’s some problem with the manifest file. Remember when I said, that jar
is a compressed file? Well, it’s a zip. So we can actually browse its contents with tools like vim by running vim Main.jar
.
" zip.vim version v28 " Browsing zipfile /home/gonczor/Projects/blog/Jars/Main.jar " Select a file with cursor and press ENTER META-INF/ META-INF/MANIFEST.MF Main.class
OK, some manifest has been created for us. Let’s look at its contents.
Manifest-Version: 1.0 Created-By: 11.0.10 (Ubuntu)
The problem is that it does not tell the JVM where it should start executing the jar. There’s no entrypoint. In Assembly, we expect an address of the first instruction in the data
section, here we expect the name of the place to start the execution (you may want to look at some reverse engineering stuff I did or look at some assemblies).
Luckily, we can add such info to the Java Manifest file. Let’s create a text file called manifest.txt
:
Main-Class: Main
And merge it into current jar. To do this we need one extra parameter to our command.
jar -cfm Main.jar manifest.txt Main.class
The m
letter tells to add contents of the manifest.txt
to the Main.jar
, which will also include the Main.class
. Does it work now?
$ java -jar Main.jar Hello, world!
Summary
Jars are way more powerful than just creating executables. They can help to sign the code and do other magic that is currently beyond my comprehension. I hope, however, that you got your “AHA” moment, just like I got mine a few minutes ago.
That’s all folks, happy hacking.