文章目录

  • 前言
  • 一、jar包是什么?
  • 二、他们的区别
    • 1.功能目的
    • 2.文件目录
      • 相同点:
      • 不同点:
    • 3.运行原理
      • 1.springboot的入口
      • 2.Springbootloader作用
  • 总结
  • 额外补充
    • Java → JVM → glibc → 内核 [JVM启动过程源码流程分析](https://blog.csdn.net/u014106644/article/details/89428482)

前言

刚学java时,我们还都不会用ide,那会我们都直接使用javac编译,java来运行;但都是针对单个文件;这个是容易理解的;可当一个完整项目的springboot 的jar包通过java -jar 后是如何运行的呢?


一、jar包是什么?

首先我们要知道java是不支持jar包中内嵌jar包的读取的;所以像springboot打包好的jar包,里面是有lib文件夹,里面全是*.jar。这种情况单靠java是不可能读取里面的class文件的。
对于jar文件,我们首先要明白它实际上是哟有两种情况的:

  1. 一种就是咱们经常能看到的,通过springboot打包好的可运行jar,这是一种;
  2. 还有一种就是我们缺少思考没有想过,但却能看到的,就是我们开发引用的jar包,也就是springboot打包好的jar包中的lib文件夹下的jar包,这些jar包,或者说依赖,也都是一个个单独的jar包;

二、他们的区别

1.功能目的

虽然都是以.jar结尾,但功能不同:一个是可运行的jar,目的就是为了可以单独运行;一个是作为依赖的jar(它是不能单独运行的,即使它有内置tomcat也不行的),目的就是被别人引用;

2.文件目录

下图是一个可运行jar的内部目录结构和一个依赖jar的内部结构

图1 这是一个简单Springboot项目的目录结构 图2 这是logback-classic-1.2.10.jar的目录结构

这个只是给出了目录结构,具体不同,大家可以自己找两个jar包仔细对比的看下。这里只说结论:

相同点:

1.META-INF目录下都有maven目录,这个目录里面放着pom.xml的配置文件;

2.META-INF目录下都有MANIFEST.MF。

不同点:

1.BOOT-INF是可运行jar包才有的,里面classes目录是咱们写的代码的classs文件,另一个lib就是其他依赖jar包的位置;
2.普通的依赖jar包,则是直接将业务放到与META-INF同级的目录中。
3.可运行jar的META-INF下无services目录,普通jar有

4.都有的org目录,但里面东西却不同。

3.运行原理

我们知道tomcat在没有项目的情况下也是能独立启动的,java一样,即使没有jar包运行,单独也是可运行的,就是我们的jvm。jvm的启动加载运行jvm类加载机制与过程,这里就不再赘述了。

1.springboot的入口

还记得上面的MANIFEST.MF文件吗

这个就是springboot的入口,而这个文件的位置就是根目录org下,这个目录是在咱项目打jar包的时候就生成了的。spring-boot-loader是SpringBoot的引导程序,当你使用Maven-Install打包一个SpringBoot单一JAR包时,SpringBootLoader的代码被拷贝到JAR中。(即这个org目录)

SpringBootLoader读取内嵌JAR资源的关键(内嵌JAR以STORED模式存储)(即:非压缩,另一个模式是:DEFLATED)

2.Springbootloader作用

我们看到,SpringBootLoader:

  1. 接管了SpringBoot程序的启动入口(Main-Class)
  2. 对JDK中java.util.zip.ZipFile实现了扩展,以便支持内嵌JAR中class的随机访问
    3.提供了SpringBoot-ClassLoader负责BOOT-INF下classes、lib的资源加载(Spring-Boot-Classes、Spring-Boot-Lib内容构成了应用真正的class-path)
    通俗来讲就是,我们开发认为的主方法,并不是程序运行真正的主方法,它的前面还有JarLauncher;
    4.是JarLauncher最终通过JarFile类的成员变量manifestSupplier关联上的:
    5.jvm如何识别MANIFEST.MF文件的Main-Class?

在oracle官网找到了该命令的描述:

If the -jar option is specified, its argument is the name of the JAR
file containing class and resource files for the application. The
startup class must be indicated by the Main-Class manifest header in
its source code.

再次秀出我蹩脚的英文翻译:

  1. 使用-jar参数时,后面的参数是的jar文件名(本例中是springbootstarterdemo-0.0.1-SNAPSHOT.jar);
  2. 该jar文件中包含的是class和资源文件;
  3. 在manifest文件中有Main-Class的定义;
  4. Main-Class的源码中指定了整个应用的启动类;(in its source code)

小结一下:
java -jar会去找jar中的MANIFEST.MF文件的Main-Class,在那里面找到真正的启动类;


总结

所以,从jvm到springboot,实际流程如下。

操作系统底层c/c++启动jre --> 找到MANIFEST.MF文件通过JarLauncher --> Application.java的main方法


额外补充

上面主要讲了springboot的主类是如何被java找到的,但jvm是如何找到JarLauncher的呢?

下面是我找的一个解释:

1.首先main方法执行需要一个操作来启动,像java Mm这种命令
2.这种命令首先是操作系统解析找到java命令属于jdk的东西,并调用jdk的的启动函数, 就像windows的双击操作一样,双击肯定是操作系统搞了什么小动作打开了软件
3.当操作系统调用了虚拟机的命令后,虚拟机会拿到命令的参数比如 Mm,然后去找编译后的文件
4.虚拟机找到文件后会调用jdk中的java代码,找到这个类sun.launcher.LauncherHelper,这个类作为一个工具类,作为桥梁链接了c++和java代码
5.调用sun.launcher.LauncherHelper类的checkAndLoadMain方法,通过这个方法找执行类Mm的Main方法
6.加载好之后执行Main

这是另一个解释:

在JavaMain()函数(定义在openjdk/jdk/src/share/bin/java.c文件中)中调用LoadMainClass()函数加载Java主类。

我们先看下LoadMainClass的细节,看看她咋加载的。通过GetLauncherHelperClass方法,我们终于看到了熟悉的身影:sun/launcher/LauncherHelper

LoadMainClass做了三件事:
1、获取LauncherHelper实例
2、通过checkAndLoadMain方法使用ClassLoader.getSystemClassLoader初始化org.springframework.boot.loader.JarLauncher class
3、makePlatformString获取utf-8后的string

下面附上这个类的截图


在jvm核心包rt.jar中。

Java 离 Linux 内核到底有多远?
第 1 步,调用 InitializeJVM 初始化 JVM。InitializeJVM 会调用 ifn->CreateJavaVM,也就是libjvm.so 中的 JNI_CreateJavaVM。

第 2 步,LoadMainClass,最终调用的是 JVM_FindClassFromBootLoader,也是通过动态链接找到函数(定义在 hotspot/share/prims/ 下),然后调用它。

第 3 和第 4 步,Java 的同学应该知道,这就是调用 main 函数。

加载主类LoadMainClass
LoadMainClass执行过程,主要是利用JNI方法来获取主类名称,进行类名处理,以及加载主类。

LauncherHelper你的祖坟终于找到了!!!

Java → JVM → glibc → 内核
JVM启动过程源码流程分析

java -jar xx.jar是如何运行的相关推荐

  1. java 启动方式 java -jar xx.jar

    1.窗口被锁定,可按CTRL + C打断程序运行,关闭窗口程序停止运行 java -jar XXX.jar 2.窗口不被锁定,关闭窗口时,程序停止运行 java -jar XXX.jar & ...

  2. java -jar xx.jar 时报错:Exception in thread main java.lang.UnsupportedClassVersionError:

    在linux服务器上运行java -jar xxx.jar 时报错 :Exception in thread "main" java.lang.UnsupportedClassVe ...

  3. java jar 最大内存大小_Java运行Jar包内存配置的操作

    Java运行Jar包内存配置的操作,内存,大小,空间,最小,这是 Java运行Jar包内存配置的操作 易采站长站,站长之家为您整理了Java运行Jar包内存配置的操作的相关内容. 如下: java - ...

  4. maven install后,java -jar XXXX.jar运行---找不到主类问题 以及 虚拟机中执行jar包后 访问页面出现Java heap space等其他问题

    这是前几天遇到的问题了,当天晚上想写下来来着,后来有事情就一直搁置到现在了. 由于我想将SpringCloud项目都导出jar包在虚拟机上运行,然后本地访问,所以先将SpringCloud中的注册中心 ...

  5. 将Java程序打jar包并运行

    1)接着上篇博客继续说手动编译之后,将代码打成jar包,然后直接"java -jar lz.jar"运行不成功的问题.还是先上代码: 这个是Demo类: package org.l ...

  6. Eclipse中将java类打成jar包形式运行

    记录一次帮助小伙伴将java类打成jar包运行 1.创建java project项目 file > new > project > java project 随便起一个项目名称,fi ...

  7. linux java jar打包_【Java】Java程序打包成jar包在Linux上运行

    当需要把在Windows上开发的Java程序用在Linux上运行时,就需要吧该Java程序打包成jar包上传到Linux上去运行. 1.Java程序用MyEclipse打包成可运行的jar包 (1)在 ...

  8. java生成cmd jar包_Java程序运行机制及cmd编译运行探究(二) cmd编译运行Java程序并打成jar包...

    目标:写一个RandomUtils.java工具类,返回一个随机数,并把这个类的字节码文件打成jar包 在Java运行机制及cmd编译运行探究(一)准备工作一文中,我总结了一部分要用到的cmd及编译运 ...

  9. java jar 启动项目,SpringBoot项目运行jar包启动的步骤流程解析

    SpringBoot项目在开发中,方便快捷,有一点原因就是SpringBoot项目可以打jar包运行:把jar包直接扔服务器上,然后运行jar包就能访问项目接口了.下面介绍SpringBoot项目打j ...

最新文章

  1. ionic开发中页面跳转隐藏底部Ttab
  2. python相关概念
  3. 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)
  4. Common Knowledge_快速幂
  5. (转载)控制反转(IoC)与依赖注入(DI)
  6. 任务不再等待!玩转DataWorks资源组
  7. shell echo 彩色字体
  8. numpy库学习总结
  9. 喜马拉雅下载成mp3方法
  10. qq音乐主页 思路解析(及代码)
  11. WRF/CMAQ 安装教程
  12. 用Angular实现图片上传问题
  13. git core.autocrlf配置说明
  14. pytest框架中setup、teardown和setup_class、teardown_class
  15. 魔数湖南大学程序设计作业
  16. 微信公众号获取关注页面链接
  17. 申论(基础题)之基础题型梳理
  18. 制作apt-get本地源解决无网络情况下安装软件
  19. Auto.js实例京东领金豆
  20. 支持多商家在线客服系统源码

热门文章

  1. SpringCloud系列之服务注册中心(Eureka)
  2. TTL与CMOS使用区别
  3. python读取txt文件并分割成列表_在python中读取文本文件并将其拆分为单个单词
  4. Linux 中 4 款炫酷的终端应用程序
  5. 【语言之美】東(dōng)杲(gǎo)杳(yǎo)
  6. 思科刀片服务器系统,思科UCS平台:B460 M4刀片服务器解读
  7. 最经典的《资本论》讲座
  8. Excel 打开无法显示内容
  9. ART–KOHONEN neural network for fault diagnosis of rotating machinery(翻译)
  10. 工业控制计算机是微型计算机吗,计算机工业控制复习题及答案