The last Java wrapper script
By user12619391 on Feb 20, 2006
One of my biggest Java pet peeves is the fact that a pristine, platform-independent Java application will frequently be shipped wrapped in a diseased blanket of shell scripting. Nominally, this wrapper script is there to set up the class path and invoke Java, acting as "glue" between the curmudgeonly operating system and this denarian virtual machine technology. The typical wrapper script is far from so reserved, unfortunately acting as a lint trap for all manner of minor enhancements presumably made in the name of programmer efficiency. In the long term, gratuitous use of multiple languages when one will do is the antithesis of efficiency (I am, of course, thinking of the poor guy who has to debug or maintain this stuff after the original author has skipped town).
As it turns out, a couple operating systems have support for direct execution of Java binaries. Coupled with an appropriately constructed JAR manifest (which can specify things often relegated to the wrapper script, e.g. the class path), this lets us eliminate these unsightly wrapper scripts in many cases.
Not all operating systems are so fortunate, though. I noticed this evening that trying to directly execute a chmodded JAR file under MacOS X gives me a disappointing "cannot execute binary file" error. To avoid introducing yet another garbage-collecting monstrosity to the world, and to avoid needing to create a new script for each new JAR I added to my growing army of Java commands, I decided to borrow a page from the isaexec playbook:
#!/bin/ksh -p # # runjava.sh: executes the JAR file whose name is used to run this script # BASE="$(basename $0)" DIR="$(dirname $0)" JARFILE="$DIR/jars/$BASE.jar" [ -f "$JARFILE" ] && exec java -jar "$JARFILE" "$@" echo runjava.sh: $BASE: command not found exit 127
runjava.sh simply takes argv as the name of a .jar file in the jars subdirectory of the directory argv is in. Using it is as simple as creating a link to it. For example, I put mycmd.jar in ~/bin/jars, and linked ~/bin/mycmd to the script. Done.
Unfortunately, not all Java applications can be simplified in this manner. Class paths may vary from install to install (something like $ORIGIN here would be a dream come true), and LD_LIBRARY_PATH might be needed to find native libraries. I'm keeping my eye on JSR 277; hopefully it will provide the solution my fellow wrapper-script haters and I long for.