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

相关推荐
毕设源码-郭学长1 小时前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
梨落秋霜2 小时前
Python入门篇【文件处理】
android·java·python
Java 码农2 小时前
RabbitMQ集群部署方案及配置指南03
java·python·rabbitmq
哈库纳玛塔塔2 小时前
放弃 MyBatis,拥抱新一代 Java 数据访问库
java·开发语言·数据库·mybatis·orm·dbvisitor
S***q3773 小时前
Spring Boot管理用户数据
java·spring boot·后端
天“码”行空3 小时前
java面向对象的三大特性之一多态
java·开发语言·jvm
毕设源码-郭学长3 小时前
【开题答辩全过程】以 基于SpringBoot框架的民俗文化交流与交易平台的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
好大哥呀4 小时前
Java Web的学习路径
java·前端·学习
f***14774 小时前
SpringBoot实战:高效实现API限流策略
java·spring boot·后端
on the way 1234 小时前
day06-SpringDI 依赖注入
java·spring