Friday, August 03, 2007

JAR is a bitch, and then you die!

[WARNING: This is geeky stuff, if you're NOT a computer geek, then scroll down to the next post. Move along, nothing to see here!]

Instead of the old adage "Life's a bitch, and then you die" I propose a new version: "JAR is a bitch, and then you die".

In case you're living in a bottle or you're not a geek, JAR is the Java JDK tool used to build the compressed ".JAR" (Java Archive) files that contain a Java software application (all the different binary files inside it). It's a tiny command line application just like everything in the JDK that should be no different or more complex to use than ZIP or tar.

However, it proved to be a real pain in the ass and a TIME WASTING EXERCISE, just to update a SINGLE TEXT LINE inside an existing .jar file's "Manifest".

1. What I wanted to do:
Unpack an existing application,
update its MANIFEST file, to include the "Main-Class: ClassnameHere" statement, so I could just start the application by typing

java -jar applicationname.jar
instead of using the author's ancient approach of having to name the "Main-Class" on the command-line every time...

java -classpath applicationname.jar LongNameofTheStupidStartupClass
2. I unpacked the existing application's .jar file just fine with 'unzip', and created a text file with my favorite text editor which read:

Main-Class: LongNameofTheStupidStartupClass

I saved it as "./manifestinfo.txt"

3. So, not having used jar before, I go to a tutorial I find online here

which reads

"The basic command has this format:

jar cfm jar-file manifest-addition input-file(s)

...and thinking I know what I'm doing, I type:

$ jar -c jftpd.jar ./manifestinfo.txt ./ ./ftpserver/*

I get this as a result:

4. I had to close the terminal as I couldn't type anymore (I could type but I couldn't understand anything).

Then I found what I think is a more friendly explanation on how to update the "Manifest" of the .JAR file with new info, over HERE:

(Later I realize that what happened in Step#3 was that I forgot to include the "f" parameter to indicate that I wanted output to a file rather than to STANDARD OUTPUT. What the **** is the purpose of having output of JAR to standard output?? I don't get it).

5. So I type
jar cf jftpd.jar ftpserver/*
But I forgot about the new manifest info... so I type:

$ jar umf ./manifestinfo.txt ./jftpd.jar
...and I get this beauty: misplaced continuation line
at java.util.jar.Manifest.(
[fcassia@m6810 tmp]$


6. You know what was the problem? the file "manifestinfo.txt" had TWO BLANK SPACES before the text "Main-Class: ..." and TWO BLANK LINES below it !! (I pressed [Enter] twice).

Apparently, JAR FREAKS OUT (this is JAVA 6.0 update 2 JDK's JAR, for crying out loud!).

7. I removed the two leading spaces and trailing blank lines and guess what? IT WORKED!.

[fcassia@m6810 tmp]$ jar umf ./manifestinfo.txt ./jftpd.jar
[fcassia@m6810 tmp]$

8. Done.... BASTARDS!!

9. Another Golden Rule when dealing with JAR:

So, contradicting what would be the 'zip' usage of "hey zip, I want to update THIS ZIPFILE with THIS_DATA" (zip newfile.txt) in JAR is totally the opposite way: "hey JAR, I want THIS NEW FILE into THISJAR" (jar umf newdata ./intothisjar.jar).


And finally, found this thread

See comment #11:
The JAR tool is rather finicky. I have found that each HEADER:VALUE pair must be separated by a newline but not more than 1 newline. When I tried putting blank lines in the MANIFEST, I would get "Error: failed to load Main-Class attribute...". Sun needs to update their tutorials or fix this problem with the JAR tool's manifest parser."

FINICKY? That's being mercyful...

and then comment #15:

"One diference between unix and windows' file system is that text files in unix always have a final linebreak at the end of the file, while windows doesn't need to.

Java, being developed by Sun primarily for the unix comunity requires that the
manifest file ends with a new-line.

no new-line, no manifest file."


Want more? See the comments on page #2 of the above thread at, discussing the "joys" of the "jar" command:

Does this instruction really work???

They specify the following command:
jar cmf MyJar.jar Manifest.txt MyPackage/*.class

When I tried that with my classes and files (with different names, of
course), it didn't work. What worked for me is equivalent to the
jar cmf Manifest.txt MyJar.jar MyPackage/*.class

The order is simply permuted. Maybe it's just Apple's Java
implementation. Is this what you were asking about?



The Tutorial is wrong. It should be jar cfm, not cmf.
The order of the command must match the order of the parameters.


Thank you. That is good to know.





Karim Vaes said...

If you can't type anymore (like you had in the post above), then do a "reset" in your terminal. In the xfce-terminal, this can be done by going to the "Terminal" menu, and then press "Reset".

Fernando (Nerd Gaucho) said...

Thanks for the comment, Karim!. I learn something new about Linux every day, even when I think I know plenty...

I never used the "reset" option and I thought it had to do with sending a conection reset to a Telnet session. :)

So thanks for the heads-up!