Spring Boot有一个很方便的功能就是可以将应用打成可执行的Jar。那么大家有没想过这个Jar是怎么运行起来的呢?本篇博客就来介绍下Spring Boot可执行Jar包的运行原理。


1. 打可执行Jar包

将Spring Boot应用打成可执行Jar包很容易,只需要在pom中加上一个Spring Boot提供的插件,然后在执行mvn package即可。

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

注意:

如果你的项目没有继承spring-boot-starter-parent这个POM,你需要做如下配置,将目标绑定到repackage。

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

关于这个插件的详细使用,可以参考官网

运行完mvn package后,我们会在target目录下看到两个jar文件。myproject-0.0.1-SNAPSHOT.jar和myproject-0.0.1-SNAPSHOT.jar.original。第一jar文件就是我们应用的可执行jar包,第二个Jar文件是应用原始的jar包。

2. 可执行Jar包内部结构

将打出来的可执行Jar解压开我们能看到下面的结构:

可执行jar 目录结构
├─BOOT-INF
│ ├─classes
│ └─lib
├─META-INF
│ ├─maven
│ ├─app.properties
│ ├─MANIFEST.MF
└─org
└─springframework
└─boot
└─loader
├─archive
├─data
├─jar
└─util

我们先来重点关注两个地方:META-INF下面的Jar包描述文件和BOOT-INF这个目录。

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: xxxx
Start-Class: com.xxxx.AppServer
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.1.6.RELEASE
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_73
Main-Class: org.springframework.boot.loader.JarLauncher

在上面我们看到一个熟悉的配置Main-Class: org.springframework.boot.loader.JarLauncher。我们大概能猜到这个类是整个系统的入口。

再看下BOOT-INF这个目录下面,我们会发现里面是我们项目打出来的class文件和项目依赖的Jar包。看到这里,你可能已经猜到Spring Boot是怎么启动项目的了。

3. JarLauncher

public class JarLauncher extends ExecutableArchiveLauncher {

	static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";

	static final String BOOT_INF_LIB = "BOOT-INF/lib/";

	public JarLauncher() {
} protected JarLauncher(Archive archive) {
super(archive);
} @Override
protected boolean isNestedArchive(Archive.Entry entry) {
if (entry.isDirectory()) {
return entry.getName().equals(BOOT_INF_CLASSES);
}
return entry.getName().startsWith(BOOT_INF_LIB);
} public static void main(String[] args) throws Exception {
//项目入口,重点在launch这个方法中
new JarLauncher().launch(args);
} }
//launch方法
protected void launch(String[] args) throws Exception {
JarFile.registerUrlProtocolHandler();
//创建LaunchedURLClassLoader。如果根类加载器和扩展类加载器没有加载到某个类的话,就会通过LaunchedURLClassLoader这个加载器来加载类。这个加载器会从Boot-INF下面的class目录和lib目录下加载类。
ClassLoader classLoader = createClassLoader(getClassPathArchives());
//这个方法会读取jar描述文件中的Start-Class属性,然后通过反射调用到这个类的main方法。
launch(args, getMainClass(), classLoader);
}

4. 简单总结

  • Spring Boot可执行Jar包的入口点是JarLauncher的main方法;
  • 这个方法的执行逻辑是先创建一个LaunchedURLClassLoader,这个加载器加载类的逻辑是:先判断根类加载器和扩展类加载器能否加载到某个类,如果都加载不到就从Boot-INF下面的class和lib目录下去加载;
  • 读取Start-Class属性,通过反射机制调用启动类的main方法,这样就顺利调用到我们开发的Spring Boot主启动类的main方法了。

5. 远程调试

这边介绍个调试JarLauncher启动的小技巧--IDEA 远程调试

step1:我们以下面的方式启动我们的Spring Boot应用

 java -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y -jar App.jar

step2:在idea中进行如下配置

然后点击下面的执行按钮执行即可:

6. 公众号推荐

欢迎大家关注我的个人公众号「程序员自由之路」

Spring Boot可执行Jar包运行原理的更多相关文章

  1. Spring Boot部署之jar包运行

    上篇阐述了Spring Boot war部署项目,本篇阐述另一种运行方式:jar包运行. 一.打jar包 1.修改pom.xml配置 2.执行package(对于module执行package之前需要 ...

  2. 关于spring boot打出的jar包在Linux中运行

    众所周知, spring boot打出的jar包可以通过 "java -jar xxx.jar"的方式来运行 但是在Linux中, 通过这个命令运行的话会占用该窗口, 当我们 Ct ...

  3. Spring Boot项目生成jar包,并在windows服务器中注册成服务,开机启动

    背景: 使用Spring Boot开发的Web项目,打包生成了一个jar包,希望能部署在Windows服务器中 尝试: 1.Spring Boot生成的jar包,可以直接用java -jar运行,但是 ...

  4. Gradle 如何打包 Spring Boot 可执行 JAR

    如何在 Gradle 中配置一个项目可以打包为 Spring Boot 可执行 Jar? 你首先需要添加到 org.springframework.boot 到插件中: 例如下面的代码: plugin ...

  5. spring boot开发,jar包一个一个来启动太麻烦了,写一个bat文件一键启动

    spring boot开发,jar包一个一个来启动太麻烦了,写一个bat文件一键启动 @echo offcd D:\workProject\bushustart cmd /c "title ...

  6. Spring框架学习笔记(6)——阿里云服务器部署Spring Boot项目(jar包)

    最近接外包,需要部署服务器,便是参考了网上的几篇博文,成功在阿里云服务器成功部署了Spring Boot项目,特记下本篇笔记 Spring Boot项目打包 这里说一下部署的一些问题 1.mysql驱 ...

  7. spring boot工程打成JAR包到服务器上运行

    只需在项目的pom.xml中加入下面插件 <build> <plugins> <plugin> <groupId>org.springframework ...

  8. 1.Spring Boot入门及其jar包依赖模型分析

    Spring Boot介绍 Spring Boot是由Pivotal团队提供的新框架,其设计目的是简化Spring应用的搭建以及开发过程.其目标是: 为所有Spring开发提供一个从根本上更快,且方便 ...

  9. spring boot中,jar包、war包的区别

    jar包.war包 比较(表格) 项目 jar包 war包 在开发调试完成之后,可以将应用打成JAR包的形式,可以直接使用Maven插件的package命令,最终会形成一个可运行的 JAR包.我们使用 ...

随机推荐

  1. 如果你不了解Java的JVM,那真的很难进BAT一线大厂!

    前言 对于开发人员来说,如果不了解Java的JVM,那真的是很难写得一手好代码,很难查得一手好bug.同时,JVM也是面试环节的中重灾区.我们不能为了面试而面试,但是学习会这些核心知识你必定会成为面试 ...

  2. Centos7调整root分区大小

    由于centos安装完毕后一般给root只有50G左右,而home牛大, 所以多数时候需要把home弄小,root给扩展大一点 折腾一下 首先切好用户到root用户登陆,我用的systemctl se ...

  3. 如何在Android手机上进行自动化测试(下)

    版权声明:允许转载,但转载必须保留原链接:请勿用作商业或者非法用途 前言 通过阅读本篇教程,你将会了解到: 如何使用Poco对Android原生应用进行测试 Poco支持直接对任何Android原生应 ...

  4. SQL- SQL插入与更新删除

    一 前言 经过之前的 [SQL]-SQL介绍, [SQL]- SQL检索阶段一, [SQL]-sql检索阶段二 的三篇文章你已经学会的sql的相关概念和如何查询数据库,这篇文章主要后续对数据库表的进入 ...

  5. GeoSpark入门-可视化

        GeoSpark是一种用于大规模空间数据处理的集群计算. GeoSpark通过一组out-of-the-box空间弹性分布式数据集( SRDDs ) 扩展 Apache Spark,它可以跨机 ...

  6. MySQL数据库~~~~初识、基础数据类型

    一 数据库初识 1.1 什么是数据库 数据库(DataBase,简称DB),简而言之可视为电子化的文件柜----存储电子文件的处所,用户可以对文件中的数据运行新增,截取,更新,删除等操作. 所谓数据库 ...

  7. PHP中使用date获取上月最后一天出现的问题

    上次做项目时,发现一个问题,这里记录一下: 问题: 在使用date函数获取上一个月最后一天或下个月最后一天时,如果当前日期是31号,获取的数据有问题. // 2019-12-01 正确应该是 2019 ...

  8. laravel身份验证-Auth的使用

    laravel自带了auth类和User模型来帮助我们很方便的实现用户登陆.判断.首先,先配置一下相关参数 app/config/auth.php: model 指定模型table 指定用户表这里我只 ...

  9. strcmp函数和memcmp函数的用法区别及联系

    前言: C语言中有很多东西容易搞混,最近笔者就遇到了一个问题.这里做个记录.就是memcmp和strcmp两者的用法,这里做个对比: 功能对比: A memcmp: 函数原型: int memcmp( ...

  10. 基于MbedTLS的AES加密实现,含STM32H7和STM32F4的实现例程

    说明: 1.mbedTLS的前身是PolarSSL,开源免费. 主要提供了的SSL/TLS支持(在传输层对网络进行加密),各种加密算法,各种哈希算法,随机数生成以及X.509(密码学里公钥证书的格式标 ...