【图灵学院】Spring Boot应用的jar是怎么执行的?

将Spring Boot项目打包成jar之后,我们通常会使用如下命令去运行:

当Spring Boot应用可执行jar文件被java -jar执行时,其命令本身对jar文件是否来自Spring Boot插件打包并不感知。换言之,java -jar命令引导的是标准可执行jar文件,按照Java官方文件的规定,java -jar命令引导的具体启动类必须配置在MANIFEST.MF资源的Main-Class属性中,同时,根据jar文件规范,MANIFEST.MF资源必须存放在/META-INF/目录下,这里我们解压Spring Boot应用的jar文件来看看具体的文件目录。这里为了更好的展示,我们把lib目录下的依赖jar先删除。

我们可以看到在/META-INF/目录下存在MANIFEST.MF,里面的内容如下:

发现Main-Class属性指向的Class为org.springframework.boot.loader.JarLauncher,而该类存放在org/springframework/boot/loader目录下,并且项目的引导类定义在Start-Class属性中,该属性并不是Java平台标准META-INF/MANIFEST.MF中的属性。

启动类org.springframework.boot.loader.JarLauncher并非项目中的文件,而是由spring-boot-maven-plugin插件repackage追加进去的,其所在的jar文件的maven GAV信息为org.springframework.boot:spring-boot-loader:2.0.2.RELEASE。通常情况下,这个依赖没有必要引入Spring Boot项目的pom.xml文件。既然org.springframework.boot.loader.JarLauncher类文件存在于jar文件中,那么也就可以通过java命令在解压目录下启动该类文件。

实际运行的结果证实了刚才的推测,同时从控制台输出分析,项目引导类com.example.nacosconfig.NacosConfigApplication被JarLauncher装载并执行,换言之,META-INF/MANIFEST.MF资源中的Start-Class属性被JarLauncher关联项目引导类,反之,如果直接使用java命令引导com.example.nacosconfig.NacosConfigApplication,命令执行后,JVM运行失败,提示类org.springframework.boot.Spring.Application无法找到,不难理解,这是由于java命令未指定Class Path。而当前Spring Boot依赖的JAR文件均存放在BOOT-INF/lib目录下。org.springframework.boot.loader.JarLauncher会将这些JAR文件作为NacosConfigApplication的类库依赖,所以JarLauncher能够引导,反之NacosConfigApplication则不行,那么NacosConfigApplication的执行进程到底属于JarLauncher的子进程,还是与JarLauncher处于同一进程?实际上,JarLauncher是同进程内调用Start-Class类的main(String [])方法,并且在启动前准备好Class Path。