jar -jar运行原理

jar -jar运行原理

1.前言

阅读这篇文章你将知道

jar包是如何被jvm加载,并运行起来的。

jvm的classload如何进行加载

springboot对象的生命周期啥时候开始的

2.提问

平时我对于java代码是如何运行起来的缺少认知,那么java代码是如何运行起来的呢?

3.前置知识

jvm类加载原理:双亲委派基金,二进制字节码,spi知识点需要复习,jar包的结构

jar包的结构如下:

run.jar

|------org

| |------springframework

| |------boot

| |------loader

| |------JarLauncher.class

| |------Launcher.class

|------META-INF

| |------MANIFEST.MF

|------BOOT-INF

| |------class

| |------Main.class

| |------Begin.class

| |------lib

| |------commons.jar

| |------plugin.jar

| |------resource

| |------a.jpg

| |------b.jpg

4.运行原理

在idea中我们点击运行其实经历了以外几步:1.clean->compile→install(其实就是编译和打包),得到一个jar包

编译的过程其实就是将java代码,编译成一个一个.class文件(二进制字节码),这个也是jvm的一个优点,二进制字节码是脱离语言而存在的,这里就能体现一次编码,到处都可以运行。

java真正运行起来是通过jar -jar来进行的,那么jar -jar完会直接去找Main-Class

即找到META-INF下面的MANIFEST.MF文件里的Main-Class的属性值。也就是org.springframework.boot.loader.JarLauncher,这是一个用于jar这种归档文件的启动器,它的直接父类是ExecutableArchiveLauncher类,这个父类有两个子类,另一个是WarLauncher,然后会执行里面一个入口方法,也就是main方法

main方法里创建了一个JarLauncher实例,并执行了它的一个launch方法,这个方法位于父类Launcher类中,通过一个getClassPathArchives方法获取到我们执行的那个jar归档文件

然后通过getNestedArchives方法获取到boot-inf里面的第三方jar包和项目中的信息,也就是嵌套的jar文件,随后创建一个LaunedURLClassloader(自定义类加载器),把Launcher这个类的类加载器作为它的父类加载器,并且把线程上下文类加载器设置成该类加载器,这个类加载器是springboot自定义的类加载器,用于加载jdk提供的类加载器所加载不到的被嵌套的jar文件和项目类信息,

拿到Start-class的属性值,也就是我们自己定义的springbootapplication的启动类,用这个类加载器去加载这个启动类, 接下来通过反射的方式去执行main方法

springbootapplication启动之后会进行spring对象生命周期的过程中,通过autoconfigration还有扫描注解将bean加载到springfactory里面

注意:jar -jar第一步是将所有的字节码存入内存,但是并不是所有的内容都加载到classloader里面,jvm是对特定的对象通过双亲委派来进行加载到内存的

5.classpath的几种读取方式

5.1 classpath是啥

classpath是存放.class文件的根路径,这个根路径是如何获取到呢,是在jdk源码classloader包里面有定义,被定义为classloader的资源.

5.2 classpath的读取方式

由于classpath的数据来源是jdk,classloader,spring还有线程读取classload的方式都是异曲同工,原理都是调用classload的getResource方法,常用的方法有:

5.2.1 class.getClassloader()

Class.getResource(String path)

path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源。在这里'/'表示ClassPath

JDK设置这样的规则,是很好理解的,path不以'/'开头时,我们就能获取与当前类所在的路径相同的资源文件,而以'/'开头时可以获取ClassPath根下任意路径的资源。

5.2.2.classload.getResource()

Class.getClassLoader().getResource(String path)

path不能以'/'开头时,path是指类加载器的加载范围,在资源加载的过程中,使用的逐级向上委托的形式加载的,'/'表示Boot

5.2.3.resourceUtil.getURL("classpath:").getPath() (springboot的方式)

这种方式其实是封装了classload.getResouce方式即获取当前线程类加载器 然后去获取classloder的资源

6参考

https://blog.csdn.net/gml0000/article/details/105334331

https://blog.csdn.net/l18848956739/article/details/97514462

相关推荐
Lhappy嘻嘻8 小时前
Java IO|File 文件操作 + 字节流 / 字符流完整笔记 + 递归删除文件实战
java·笔记·php
伊玛目的门徒8 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
懒鸟一枚11 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我1234513 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑13 小时前
Sentinel安装
java·后端·微服务
凤凰院凶涛QAQ14 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
掘金_答案15 小时前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
猿与禅16 小时前
CosId 分布式 ID 生成器完全教程:从架构原理到生产落地
java·shardingsphere·雪花算法·分布式id·高性能·cosid·号段模式
MindUp16 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
NG47716 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程