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

1. 打可执行jar包

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

org.springframework.boot

spring-boot-maven-plugin

注意:

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

org.springframework.boot

spring-boot-maven-plugin

repackage

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

运行完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中进行如下配置

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

希望与广大网友互动??

点此进行留言吧!

java -jar 工作原理_可执行Jar包运行原理相关推荐

  1. python程序运行原理_谈谈 Python 程序的运行原理

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,谈谈 Python 程序的运行原理 这篇文章准确说是『Python 源码剖析』的 ...

  2. 简述python程序的运行原理_谈谈 Python 程序的运行原理

    执行 python demo.py 后,将会启动 Python 的解释器,然后将 demo.py 编译成一个字节码对象 PyCodeObject. 在 Python 的世界中,一切都是对象,函数也是对 ...

  3. Java Maven项目打包成可执行jar文件

    在pom文件中添加一下内容 <build><plugins><plugin><!-- Build an executable JAR --><gr ...

  4. java虚拟机工作原理图_超“强”的图文详解-JVM虚拟机底层原理与调优实战

    今天我和大家分享一篇文章,文章上半部分为JVM底层原理 下半部分为调优实战 文章有点长,需要点耐心哦! 如果觉得看文章太难理解,就点击下面我投稿B站的jvm视频讲解. 还配有视频讲解:解密BATJ一线 ...

  5. java线程工作原型_深度解析Java内存的原型及工作原理

    本文主要通过分析Java内存分配的栈.堆以以及常量池详细的讲解了其的工作原理. 一.java虚拟机内存原型 寄存器:我们在程序中无法控制栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是 ...

  6. nexus3手动上传jar文件(包括不可执行jar打包配置)

    前言 最近用nexus3管理工具jar包时,发现多模块依赖引用找不到依赖包,依赖包不会关联下载,一直以为是打包的问题,还尝试着把所有依赖都打进工具jar中,结果都无法正常启动项目,最后才发现是pom的 ...

  7. 海天食品的java开发工作如何_再三个月就秋招了,我想找一份java开发工作,现在应该怎么准备一下?...

    在找工作之前,大家都要做一些准备工作,java开发也是如此 掌握核心JavaSE 首先,从核心Java(JavaSE)开始学习,尽可能地掌握它.你应该了解和掌握一些基本概念,如循环,数组,运算符等等. ...

  8. jar命令的使用与执行jar包

    (1)jar命令模板 c:>jar cvfe test.jar test.Test test 把test目录下的所有文件都压缩到test.jar包中,并指定使用test.Test类(如果主类带包 ...

  9. mysql的sql执行原理图_性能测试MySQL之SQL运行原理

    一,MySQL运行原理 两个一样的图 1,SQL语句执行的过程详细说明 如上图所示,当向MySQL发送一个请求的时候,MySQL到底做了什么: a, 客户端发送一条查询给服务器. b, 服务器先检查查 ...

最新文章

  1. QT打开和保存文件对话框
  2. 数据结构:关于重建二叉树的三种思路
  3. mysql now str,数据库学习之MySQL (十)—— 日期和时间函数 NOW STR_TO_DATE DATE_FORMAT 流程控制函数 IF IFNULL CASE...
  4. 第二周CoreIDRAW课总结
  5. 【转】C#数据结构-有限状态机
  6. linux-用户与组的概念
  7. 漫步最优化十二——局部极小与极大的充分必要条件(下)
  8. EJB3.0学习笔记---Bean实现多个接口的情况下定义,访问方式:
  9. 解决Spark集群无法停止
  10. dns114.114.114..114
  11. android 获取类对象(代码片段)
  12. 索辰科技在科创板过会:拟募资金额有所下调,上半年亏损4000万元
  13. jsp自定义标签的问题Unable to load tag handler class
  14. A Transformer-based Approach for Source code Summarization 翻译
  15. 弗洛伊德算法注意项 floyd
  16. 国庆七天假期就剩下最后一天了
  17. VCNL4040传感器
  18. 新学期 新目标 新征程
  19. 《智慧书》格言11¬20
  20. 反序列化漏洞分析讲解

热门文章

  1. vue 多层表格嵌套
  2. 用C语言实现2的次方运算
  3. 1、解决Access连接 accdb 不可识别的数据库格式异常
  4. 壮美大山包-2017中国大山包国际超百公里ITRA积分赛赛记
  5. r语言 read_html,R语言外部数据读取(示例代码)
  6. vba 引用Sheet的几种方法
  7. Android 进阶之探索 OkHttp 原理
  8. 射频layout设计笔记
  9. CS品牌SD NAND在车联网行业中的应用案例
  10. chrome浏览器出现Uncaught DOMException: Failed to execute ‘postMessage‘ on ‘Window‘: HTMLUnknownElement ob