24

I am deploying a command-line tool that is written in Java that accepts command-line arguments. I have it packaged as a JAR file because it is convenient to have a single file.

The problem is that to run it you must first call java -jar (filename) (args) and that is quite annoying.

The current way I have it is to have a simple bash script that launches it, but this is less than ideal.

Is there anyway (in Linux, Ubuntu Server) to make a JAR file that invokes the Java VM by itself? I've looked for a shebang, but couldn't find one (which of course makes sense since it is compiled code).

This is what I want to do: myprogram.jar arg1 -arg2 instead of this: java -jar myprogram.jar arg1 -arg2

Thanks,
Brian

1
  • None of the answers state a better solution I read somewhere where you basically concatenate a shell command at the top of the jar file. Not elegant but very convenient. mesosphere.com/blog/executable-jars Commented Dec 12, 2017 at 23:29

3 Answers 3

45

The .zip file format (upon which the .jar format is based) seems to be robust in the presence of extra data prepended to the file. Thus if you use the cat command to put a shebang before the zip data in the jar file, and make the file executable, then you can call the jar file like you would call any ordinary shell script.

For example: (Note that the unzip -l command is just to illustrate the point. It doesn't change anything about the .jar and can be omitted when you're actually doing this process.)

[bloom@cat-in-the-hat ~]$ java -jar tex4ht.jar xtpipes (2009-01-27-22:19) Command line options: java xtpipes [-trace] [-help] [-m] [-E] [-s script_file] [-S script_map] [-i script_dir] [-o out_file] [-x...ml2xml_arg...] (-d in_data | in_file) -m messages printing mode -E error messages into exception calls in_data XML data directly into the command line [bloom@cat-in-the-hat ~]$ cat header.txt #!/usr/bin/java -jar [bloom@cat-in-the-hat ~]$ cat header.txt tex4ht.jar > tex4ht_exe.jar [bloom@cat-in-the-hat ~]$ unzip -l tex4ht_exe.jar Archive: tex4ht_exe.jar warning [tex4ht_exe.jar]: 21 extra bytes at beginning or within zipfile (attempting to process anyway) Length Date Time Name --------- ---------- ----- ---- 0 2009-07-09 15:48 META-INF/ 42 2009-07-09 15:47 META-INF/MANIFEST.MF 0 2009-07-09 15:48 ./ 0 2009-07-09 15:48 tex4ht/ 2217 2009-07-09 15:48 tex4ht/DbUtilities.class 2086 2009-07-09 15:48 tex4ht/GroupMn.class 6064 2009-07-09 15:48 tex4ht/HtJsml.class 4176 2009-07-09 15:48 tex4ht/HtSpk.class 1551 2009-07-09 15:48 tex4ht/JsmlFilter.class 2001 2009-07-09 15:48 tex4ht/JsmlMathBreak.class 6172 2009-07-09 15:48 tex4ht/OoFilter.class 3449 2009-07-09 15:48 tex4ht/OoUtilities.class 1468 2009-07-09 15:48 tex4ht/OomFilter.class 346 2009-07-09 15:48 xtpipes.class 0 2009-07-09 15:48 xtpipes/ 4071 2009-07-09 15:48 xtpipes/FileInfo.class 6904 2009-07-09 15:48 xtpipes/InputObject.class 25906 2009-07-09 15:48 xtpipes/Xtpipes.class 1238 2009-07-09 15:48 xtpipes/Xtpipes$5.class 713 2009-07-09 15:48 xtpipes/Xtpipes$3.class 1533 2009-07-09 15:48 xtpipes/Xtpipes$1.class 709 2009-07-09 15:48 xtpipes/Xtpipes$7.class 1294 2009-07-09 15:48 xtpipes/XtpipesEntityResolver.class 1235 2009-07-09 15:48 xtpipes/Xtpipes$6.class 3367 2009-07-09 15:48 xtpipes/Xtpipes$4.class 709 2009-07-09 15:48 xtpipes/Xtpipes$8.class 1136 2009-07-09 15:48 xtpipes/Xtpipes$2.class 875 2009-07-09 15:48 xtpipes/XtpipesPrintWriter.class 1562 2009-07-09 15:48 xtpipes/XtpipesUni.class 0 2009-07-09 15:48 xtpipes/util/ 5720 2009-07-09 15:48 xtpipes/util/ScriptsManager.class 1377 2009-07-09 15:48 xtpipes/util/ScriptsManagerLH.class --------- ------- 87921 32 files [bloom@cat-in-the-hat ~]$ chmod +x tex4ht_exe.jar [bloom@cat-in-the-hat ~]$ ./tex4ht_exe.jar xtpipes (2009-01-27-22:19) Command line options: java xtpipes [-trace] [-help] [-m] [-E] [-s script_file] [-S script_map] [-i script_dir] [-o out_file] [-x...ml2xml_arg...] (-d in_data | in_file) -m messages printing mode -E error messages into exception calls in_data XML data directly into the command line 
Sign up to request clarification or add additional context in comments.

13 Comments

This is a very interesting solution, although quite unorthodox.
@Daniel: agreed. the binfmt_misc solution is definitely the cleaner one, but this is a seriously cool hack ;-)
As it is so helpful, here's a one-liner to simplify creating an executable filename='tex4ht.jar' ; echo '#!/usr/bin/java -jar' | cat - $filename > ${filename%.jar} ; chmod +x ${filename%.jar}
This actually isn't a hack at all, and definitely should be the accepted answer. The Linux kernel looks for the shebang (#!) at the beginning of any file it opens for execution, and if it encounters it, executes the remainder of that line with the path of the current file as a parameter.
Do not do this, such a modified JAR broke one of my SBT builds with Scala as the classes in the JAR were not found even though the JAR was on the classpath. Removing the shebang resolved the issue.
|
19

See Documentation/java.txt in the Linux Kernel documentation, which tells you how to configure a system using the binfmt_misc kernel module to run Jar files automatically. However, this is a configuration option you change on a computer, not something you change about the jar file, so it doesn't follow the jar file from system to system.

4 Comments

That seems like a great idea, but I can't afford to install the SDK on all of the production machines. I have no problem doing small changes to the target box though. I'm very pleasantly surprised that Linux implemented that though, very impressive.
You don't need the full JDK (with the compiler) to make this work. The JRE (which you need on the production machines anyway) should be just fine.
Wow! That is a great tool. Worked very well (sans-SDK). Thanks a lot.
@HalfBrian It's funny to think that this answer landed right before the Oracle acquisition and James Gosling's resignation, and 15 years later Java SDK licensing is still as onerous as ever. Thank goodness for OpenJDK and other spinoffs.
4

On debian based distribution, it is possible to install jarwrapper

sudo apt-get install jarwrapper 

I think that this is possible to do the same thing on other distributions by installing with the same package name.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.