参考文档
https://skife.org/java/unix/2011/06/20/really_executable_jars.html
原理
- jar文件本质是属于zip格式压缩包
- zip包有个hack,可以在zip文件头部插入任意的文件行(前提没有zip文件格式关键字符)
- 利用 exec java -jar 0" @”
其中 0标示执行文件名,也就是原来的jar包名称, @表示所有参与原封不动透传给 jar -jar $0.
流程,先生成一个./waffles文件,里面内容为(下面为16进制ascii dumphex的结果)
0000000 # ! / b i n / s h \n \n e x e c
0000010 j a v a - X m x 1 G - j a r
0000020 " $ 0 " " $ @ " \n \n
记得末尾必须有换行。
然后把jar包字节追加在waffles文件末尾即可:
$ cat ./waffles-1.2.3.jar >> ./waffles
$ chmod +x ./waffles
$ ./waffles --some-flag=blue hello
maven的插件
https://github.com/brianm/really-executable-jars-maven-plugin
<!-- You need to build an exectuable uberjar, I like Shade for that -->
<plugin> <!-- 第一步,生成的jar包里面 MANIFEST.MF 指定main class--->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- note that the main class is set *here* -->
<mainClass>com.example.Main</mainClass>
</transformer>
</transformers>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<!-- now make the jar chmod +x style executable -->
<plugin> <!-- 第二步,really-executable-jar-maven-plugin 生成可以直接执行的文件-->
<groupId>org.skife.maven</groupId>
<artifactId>really-executable-jar-maven-plugin</artifactId>
<version>1.4.1</version>
<configuration>
<!-- value of flags will be interpolated into the java invocation -->
<!-- as "java $flags -jar ..." -->
<flags>-Xmx1G</flags>
<!-- (optional) name for binary executable, if not set will just -->
<!-- make the regular jar artifact executable -->
<programFile>nifty-executable</programFile>
<!-- (optional) support other packaging formats than jar -->
<!-- <allowOtherTypes>true</allowOtherTypes> -->
<!-- (optional) name for a file that will define what script gets -->
<!-- embedded into the executable jar. This can be used to -->
<!-- override the default startup script which is -->
<!-- `#!/bin/sh -->
<!-- -->
<!-- exec java " + flags + " -jar "$0" "$@" -->
<!-- <scriptFile>src/packaging/someScript.extension</scriptFile> -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>really-executable-jar</goal>
</goals>
</execution>
</executions>
</plugin>