可以直接执行运行的java应用
背景
以前还在上学的时候我有试用过exe4j,这个工具可以把一个可执行的jar文件做成一个exe文件,甚至还能制作成安装包,像普通的软件一样安装卸载。如果是java桌面应用那么exe4j肯定是很实用的工具了,但是由于java那难用且难看的gui组件,用java做的桌面应用相对较少,java更多是活跃在web服务端、后端等领域。
spring-boot
早几年的java web应用都是打包成一个war,丢到tomcat中去运行,这几年spring boot火起来之后,应用打包后就是一个可以直接java -jar运行的jar文件了,只要服务器上安装了java,就能直接运行起来。spring-boot曾经做了一个这样的功能:在给spring-boot-plugin添加了executable=true的配置后,给jar文件添加可执行的权限,那么它就可以像shell脚本一样可以直接运行,如下所示:



原理和优点本文就不详细说明了,可以查看spring-boot官方文档来了解。
缺点是只支持linux系统,没办法,谁让现在的服务器大多是linux呢?
graalvm
graalvm也是甲骨文自家做的东西,它的native-image命令也可以把你的java应用做成一个可执行文件,而且也支持windows系统。
我写了个普通的HelloWorld:

我就用这个普通的类来生成二进制可执行文件了!如下图所示:

可以看到一个普通的hello world变成了一个可执行的二进制文件,唯一的缺点可能是文件有点大?但相比于直接把一个jre放在应用中,要小很多了!
maven应用可以使用native-image-maven-plugin这个plugin来自动打包,我就不再写栗子了。
native-image也支持spring-boot的jar包,我就用刚刚的例子来试一下:

竟然报错了!其实spring-boot的jar跟普通的jar是有一点区别的233333,有兴趣的小伙伴可以自己研究一下。spring-boot需要添加一些配置才能用graalvm的native-image,我简单折腾了一下,docker报了莫名其妙的错误(摊手),唉,懒得继续看了,总之spring-boot用native-image配置会比较麻烦,而且很可能会遇到一些兼容性问题。
quakus和graalvm
quakus是近期火起来的一个框架,它跟graalvm集成的很好,可以直接通过其的maven插件生成可执行文件:

java 16
java16引入了一个jpackage的命令,根据jep的描述它是源于javafx。我下载了java16来试一下,它需要一个jar文件,我把刚刚的HelloWorld打包成一个了jar,然后使用jpackage打包,如下所示:

可以看到所有的应用文件都写入了一个文件里,也包括java运行时,可以使用jlink只引入必要的模块。
接下来就是打包成deb或者rpm等安装包了:

靠,怎么回事,我难道不是linux吗?于是我看了看源码:

我的系统是archlinux,既不是debain系也不是redhat系,所以找不到默认的打包类型,就算我指定deb或者rpm也不行,它依赖于dpkg-deb以及rpmbuild命令,所以我安装了一下这俩工具,再次运行:

成功生成deb安装包了!文件大小好像也能够接受的样子
下面是规范的说明,支持三种系统

jpackage还有很多很多的参数,可以在oracle的文档查看。
参考链接:
https://www.graalvm.org/reference-manual/native-image/
https://www.graalvm.org/reference-manual/native-image/NativeImageMavenPlugin/
https://spring.io/blog/2020/11/23/spring-native-for-graalvm-0-8-3-available-now
https://openjdk.java.net/jeps/392
https://docs.oracle.com/javase/tutorial/deployment/jar/build.html
https://docs.oracle.com/en/java/javase/16/docs/specs/man/jpackage.html