Tomcat加载一个jar包的过程 | JVM加载/初始化类的时机
1. 背景 | 问题来源2. 关于 `jar` 包2.1 为什么要把java程序打包成 `jar` 包2.2 `jar` 和 `war` 包的区别
3. JVM中类的加载过程3.1 JVM的类加载顺序3.2 JVM的中类的加载时机 | JVM中类什么时候初始化3.3 类的初始化顺序
4. Tomcat中jar包的加载顺序4.1 当使用Tomcat加载jar包时,jar包中的class文件的加载顺序是什么样子的4.2 如何使Tomcat加载一个项目中预先设定好的入口 `main` 方法
5. 参考文档
1. 背景 | 问题来源
当我在看一个项目框架的源码时,突然想到了一个问题,当使用Tomcat加载jar包时,jar包中的class文件的加载顺序是什么样子的?如何使Tomcat按需加载?或者说,如何使Tomcat加载一个项目中预先设定好的入口 main 方法?
2. 关于 jar 包
2.1 为什么要把java程序打包成 jar 包
JAR 文件带来了许多好处:
Security: You can digitally sign the contents of a JAR file. Users who recognize your signature can then optionally grant your software security privileges it wouldn’t otherwise have.Decreased download time: If your applet is bundled in a JAR file, the applet’s class files and associated resources can be downloaded to a browser in a single HTTP transaction without the need for opening a new connection for each file.Compression: The JAR format allows you to compress your files for efficient storage.Packaging for extensions: The extensions framework provides a means by which you can add functionality to the Java core platform, and the JAR file format defines the packaging for extensions. By using the JAR file format, you can turn your software into extensions as well.Package Sealing: Packages stored in JAR files can be optionally sealed so that the package can enforce version consistency. Sealing a package within a JAR file means that all classes defined in that package must be found in the same JAR file.Package Versioning: A JAR file can hold data about the files it contains, such as vendor and version information.Portability: The mechanism for handling JAR files is a standard part of the Java platform’s core API.
因此要在多平台运行java程序,先将其打包为jar包更方便
2.2 jar 和 war 包的区别
jar 包:JAR 包是类的归档文件,JAR 文件格式以流行的 ZIP 文件格式为基础。与 ZIP 文件不同的是,JAR 文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和 JVM 这样的工具直接使用。
jar包里的com里放的就是class文件,配置文件,但是没有静态资源的文件,大多数 JAR 文件包含一个 META-INF 目录,它用于存储包和扩展的配置数据,如安全性和版本信息。 war 包:war包是JavaWeb程序打的包,war包里面包括写的代码编译成的class文件,依赖的包,配置文件,所有的网站页面,包括html,jsp等等。一个war包可以理解为是一个web项目,里面是项目的所有东西。
而war包里的WEB-INF里放的class文件和配置文件,META-INF和jar包作用一样,war包里还包含静态资源的文件 总结:
war包和项目的文件结构保持一致,jar包则不一样。jar包里没有静态资源的文件(index.jsp)部署普通的spring项目用war包就可以,部署springboot项目用jar包就可以,因为springboot内置tomcat。
3. JVM中类的加载过程
3.1 JVM的类加载顺序
一个java文件从被加载到被卸载这个生命过程,总共要经历5个阶段,JVM将类加载过程分为:
加载链接(验证+准备+解析)初始化使用卸载
但值得注意的是,加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类型的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始, 这是为了支持Java语言的运行时绑定特性(也称为动态绑定或晚期绑定)。
3.2 JVM的中类的加载时机 | JVM中类什么时候初始化
关于在什么情况下需要开始类加载过程的第一个阶段“加载”,《Java虚拟机规范》中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,《Java虚拟机规范》 则是严格规定了有且只有六种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):
创建类的实例,也就是new一个对象访问某个类或接口的静态变量,或者对该静态变量赋值调用类的静态方法反射(Class.forName(“com.lyj.load”))初始化一个类的子类(会首先初始化子类的父类)JVM启动时标明的启动类,即文件名和类名相同的那个类
换句话理解上述就是,如果指明程序所需要的.class 位置,那么有可能这些.class文件会先被JVM加载进去,但不一定会被初始化,直到上述六种条件出现的时候,类才会被初始化
3.3 类的初始化顺序
父类静态块(静态成员变量)子类静态块(静态成员变量)父类代码块父类构造方法子类代码快子类构造方法
值得注意的是,静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关
如果类已经被加载: 则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法。
另外值得注意的一点就是,如果一个类运行一个main函数,这个类就直接被加载,而当main函数在类外,则类不会被加载
4. Tomcat中jar包的加载顺序
4.1 当使用Tomcat加载jar包时,jar包中的class文件的加载顺序是什么样子的
$java_home/lib 目录下的java核心api
$java_home/lib/ext 目录下的java扩展jar包
java -classpath/-Djava.class.path 所指的目录下的类与jar包
$CATALINA_HOME/common 目录下按照文件夹的顺序从上往下依次加载
$CATALINA_HOME/server 目录下按照文件夹的顺序从上往下依次加载
$CATALINA_BASE/shared 目录下按照文件夹的顺序从上往下依次加载
我们的项目路径/WEB-INF/classes下的class文件
我们的项目路径/WEB-INF/lib 下的jar文件
在同一个文件夹下,jar包是按顺序从上到下依次加载
还是从上文中所得,这些类文件仅仅只是被JVM所加载,并没有全部被初始化,而是否被初始化则由上述六个条件所决定,因此这就是JVM的按需初始化
4.2 如何使Tomcat加载一个项目中预先设定好的入口 main 方法
运行jar文件的方法是:java -jar xxx.jar 但是有时,我们希望运行里面的具体某个类,这时可以通过:java - cp xxx.jar xxx.com.xxxx 它会找到这个类的main函数,开始执行 其中-cp命令是将xxx.jar加入到classpath,这样java class loader就会在这里面查找匹配的类。
5. 参考文档
jar包和war包的区别Java中类的加载顺序介绍(ClassLoader)java 加载jar包顺序_(转)jar包的加载顺序Java-类加载和main()方法的执行顺序?java 运行指定类的main函数《深入理解Java虚拟机》,周志明