Java apps are typically packaged as JAR files. Format-wise, a JAR is actually a ZIP. ZIP file format is end-anchored; a ZIP file remains processible if random bytes are prepended to it.
Therefore, if we package a Java application as a standard standalone JAR file, make sure the Main-Class manifest attribute is properly set up, and prepend these two lines to the file:
we get a file that is, at the same file, a JAR containing all the original content, and a shell script that, when executed, invokes JVM instructing it to then interpret the JAR as a standard Java app. It also passes on all the original arguments and the exit code of the JVM, as expected.#! /bin/shexec java -jar "$0" "$@"
The result behaves pretty much like a standard binary. The primary restrictions are that JRE needs to be installed in a PATH-findable way, and suid doesn't work on such pseudo-binaries on most systems. The primary advantage is that such a binary does not depend on the host architecture or even the OS (as long as it is a Unix, that is). An interesting secondary advantage is the standard resource handling mechanism inherent in the concept of using JARs for applications.