springboot的jar包为什么可以直接运行

Spring Boot 的 .jar 包能够直接运行,主要是因为它采用了 Spring Boot Loader 作为自定义类加载器,并且使用了 可执行 JAR(fat jar) 的结构。以下是详细的技术原理:


1. Spring Boot 可执行 JAR 的结构

Spring Boot 生成的 JAR 包不是传统的 Java JAR,而是 fat jar(可执行 JAR),它包含:

  • 应用的代码(com.example.*
  • 所有依赖的第三方库
  • Spring Boot Loader(Spring Boot 特有的类加载器)
  • META-INF 目录,包含特殊的 MANIFEST.MF 配置
  • 嵌套的 JAR 依赖

一个典型的 Spring Boot JAR 结构:

your-app.jar
│── META-INF/
│── org/springframework/boot/loader/   # Spring Boot 自定义的类加载器
│── BOOT-INF/
│   ├── classes/      # 你的应用代码
│   ├── lib/          # 所有依赖的 JAR 文件
│   ├── layers.idx    # Spring Boot 2.3+ 支持的分层 JAR
│── application.properties  # 应用配置文件

其中,BOOT-INF/lib/ 目录存放了应用依赖的所有 JAR,而 BOOT-INF/classes/ 目录存放应用的代码和资源文件。


2. Spring Boot Loader 机制

Spring Boot 的核心组件 spring-boot-loader 提供了一个自定义的类加载器 Launcher,用于加载嵌套 JAR(即 BOOT-INF/lib/ 下的依赖)。

关键类

  • JarLauncher(默认):用于运行 fat jar,自动识别 BOOT-INF/lib/ 下的依赖。
  • WarLauncher:用于运行 WAR 包的 Spring Boot 应用。
  • PropertiesLauncher:支持从 application.properties 加载自定义配置。

当执行 java -jar your-app.jar 时,JarLauncher 负责:

  1. 解压并加载嵌套 JAR
    • 由于传统 Java 类加载器不支持 JAR 内嵌 JAR,Spring Boot 使用 LaunchedURLClassLoader 解析 BOOT-INF/lib/ 下的 JAR 文件。
  2. 定位 Main-Class 并启动
    • MANIFEST.MF 中定义了:
      Main-Class: org.springframework.boot.loader.JarLauncher
      
    • JarLauncher 解析 BOOT-INF/classes/META-INF/MANIFEST.MF,找到 Start-Class 并运行:
      Start-Class: com.example.Application
      
    • 这相当于执行:
      public static void main(String[] args) {
          SpringApplication.run(Application.class, args);
      }
      
  3. 优先加载 BOOT-INF/classes/ 里的代码,然后再加载 BOOT-INF/lib/ 里的依赖。

3. java -jar 如何解析 Spring Boot JAR

Spring Boot JAR 采用了一种特殊的 Zip 目录结构,使 java -jar 能够正确解析:

  • 传统 JAR:所有 .class 文件和依赖在 lib/ 目录。
  • Spring Boot JAR:使用 spring-boot-loader 解析 BOOT-INF/lib/BOOT-INF/classes/

Spring Boot 通过 修改 JAR 的 MANIFEST.MF 文件,让 java -jar 解析 JarLauncher,而不是 Java 默认的 sun.misc.Launcher

查看 MANIFEST.MF

jar -xf your-app.jar META-INF/MANIFEST.MF
cat META-INF/MANIFEST.MF

你会看到类似的内容:

Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.example.Application

当你运行:

java -jar your-app.jar

实际上等效于:

java -cp your-app.jar org.springframework.boot.loader.JarLauncher

然后 JarLauncher 负责解析 Start-Class 并启动 Spring Boot 应用。


4. 为什么普通 JAR 不能直接运行?

普通 JAR 没有 Spring Boot 的 JarLauncher 机制,也不会将所有依赖打包,因此:

  • 需要手动指定 -cp(类路径):
    java -cp my-app.jar:lib/* com.example.Application
    
  • 不能嵌套 JAR,必须将所有 JAR 解压到 lib/

Spring Boot JAR 通过 JarLauncher 解决了这些问题,使得它可以直接运行。


5. Spring Boot JAR 与传统 WAR 的区别

特性Spring Boot JAR传统 WAR 部署
运行方式java -jar app.jar部署到 Tomcat
是否包含 Tomcat内置(默认 TomcatEmbeddedServletContainer需要外部 Tomcat
依赖管理BOOT-INF/lib/WEB-INF/lib/
类加载机制JarLauncher + LaunchedURLClassLoaderServlet 容器类加载

6. Spring Boot JAR 可以直接运行的原因总结

  1. Spring Boot Loader 机制

    • 通过 JarLauncher 解析嵌套 JAR,绕开传统 Java 类加载限制。
    • org.springframework.boot.loader 提供了 LaunchedURLClassLoader,可以加载 BOOT-INF/lib/ 目录下的依赖。
  2. 自定义 MANIFEST.MF

    • 通过 Main-Class: org.springframework.boot.loader.JarLauncherjava -jar 解析 Spring Boot 自定义的类加载逻辑。
    • Start-Class 指定应用的 main 入口。
  3. 嵌套 JAR 结构

    • 依赖 JAR 被放在 BOOT-INF/lib/ 目录中,而非传统 lib/,可以自动加载。
  4. 无需外部 Tomcat

    • Spring Boot 内置 Tomcat/Jetty/Undertow 服务器,使得 Web 应用可以像普通 JAR 一样运行。

7. 其他运行方式

除了 java -jar,Spring Boot 还支持:

  1. 直接运行 main()
    mvn spring-boot:run
    
  2. 使用 java -cp 运行
    java -cp your-app.jar org.springframework.boot.loader.JarLauncher
    
  3. Docker 部署
    FROM openjdk:17
    COPY target/app.jar /app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]
    

8. 结论

Spring Boot 之所以可以直接运行 .jar,是因为:

  • 使用 JarLauncher 解析 BOOT-INF/lib/ 里的依赖
  • 自定义 MANIFEST.MFjava -jar 识别 Spring Boot Loader
  • 支持嵌套 JAR,避免 CLASSPATH 手动管理
  • 内置 Tomcat,避免传统 WAR 部署麻烦

这使得 Spring Boot 应用更加 便捷,可以一键打包、一键部署,非常适合云环境和微服务架构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蘋天纬地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值