目录
所谓类加载机制就是
虚拟机把Class文件加载到内存
并对数据进行校验,转换解析和初始化
形成可以虚拟机直接使用的Java类型,即java.lang.Class
1、装载(Load)
查找和导入class文件
(1)通过一个类的全限定名获取定义此类的二进制字节流
(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
(3)在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口
Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。在
Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口
方法区:类信息、常量、静态变量、即时编译器编译后的代码
堆:代表某个类的java.lang.Class对象
2、链接(Link)
2.1、验证(Verify)
验证的目的主要是保证被加载类的正确性
- 文件格式验证
- 元数据验证
- 字节码验证
- 符号引用验证
2.2、准备(Prepare)
为类的静态变量分配内存,并将其初始化为默认值
public class Demo1 {
private static int i;
public static void main(String[] args) {
// 正常打印出0,因为静态变量i在准备阶段会有默认值0
System.out.println(i);
}
}public class Demo2 {
public static void main(String[] args) {
// 编译通不过,因为局部变量没有赋值不能被使用
int i;
System.out.println(i);
}
}
2.3、解析(Resolve)
把类中的符号引用转换为直接引用(物理内存引用)
符号引用就是一组符号来描述目标,可以是任何字面量。
直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进
行。
3、初始化(Initialize)
对类的静态变量,静态代码块执行初始化操作
4、类加载器ClassLoader
在装载(Load)阶段,其中第(1)步:通过类的全限定名获取其定义的二进制字节流,需要借助类装载
器完成,顾名思义,就是用来装载Class文件的。
4.1类加载器分类
- Bootstrap ClassLoader 负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class或Xbootclassoath选项指定的jar包。由c++实现,不是ClassLoader子类。
- Extension ClassLoader 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
- App ClassLoader 负责加载classpath中指定的jar包及Djava.class.path所指定目录下的类和jar包。
- Custom ClassLoader 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如Tomcat、Jboss都会根据j2ee规范自行实现ClassLoader。
/** * @ClassName JvmTest * @Description: TODO * @Author 马志涛 * @Date 2020/3/31 * @Version V1.0 **/ public class JvmTest { public static void main(String[] args) { // App ClassLoader System.out.println(new JvmTest().getClass().getClassLoader()); // Ext ClassLoader System.out.println(new JvmTest().getClass().getClassLoader().getParent()); // Bootstrap ClassLoader System.out.println(new JvmTest().getClass().getClassLoader().getParent().getParent()); System.out.println(new String().getClass().getClassLoader()); } }
输出结果
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@4c873330
null
null
5、双亲委派机制
5.1、检查某个类是否已经加载
自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个ClassLoader已加载,就视为已加载此类,保证此类只被ClassLoader加载一次。
5.2、加载顺序
自顶向下,也就是由上层来逐层尝试加载此类。
5.3、打破双亲委派机制
1、Tomcat中的类加载机制
2、SPI机制