一、类加载⼦系统
- 类加载⼦系统会将某个class⽂件加载到⽅法区的内存空间中,可以理解为把class⽂件中字节码指
- 令,读取到内存中。
- 验证阶段会验证待加载的class⽂件是否正确,⽐如验证⽂件格式
- 准备阶段会为static变量分配内存并赋零值
- 解析阶段会将符号引⽤解析为直接引⽤,在⼀个字节码⽂件中,会⽤到其他类,⽽在字节码中只会
- 存⽤到的类的类名,⽽解析阶段就是会根据类名找到该类加载后在⽅法区中的地址,也就是直接引
- ⽤,并替换调符号引⽤,这样真正运⾏字节码时,就能直接找到某个类了。
- 初始化阶段会给static变量赋值,并执⾏static块
二、类加载器的分类
在JVM规范中,把类加载器分了两种:
- ⼀种是BootStrapClassLoader,这是由C和C++实现的,负责加载jre/lib下的jar包中的类,⽐如
- rt.jar中的String类
- ⼀种是继承了ClassLoader抽象类的类加载器,是由Java语⾔实现的,⽐如:
- ExtClassLoader,⽤Java实现的,加载⽬录为jre/lib/ext⽬录下的类,可以看下Launcher类中的代码
- AppClassLoader,⽤Java实现的,加载⽬录为classpath所指定的⽬录,可以看下Launcher类中的代码
- 以及其他⾃定义的,⽐如Tomcat中的WebAppClassLoader
⽐如在Launcher类中有两个静态内部类:
static class AppClassLoader extends URLClassLoader {
// ...
}
static class ExtClassLoader extends URLClassLoader {
// ...
}
通过继承URLClassLoader,最终间接继承了ClassLoader。
三、双亲委派
直接看代码:
这段代码就体现了双亲委派,通常我们⽤AppClassLoader去加载⼀个类时,AppClassLoader有⼀个 parent属性指向了ExtClassLoader,当我们⽤AppClassLoader去加载⼀个类时,会先委托给 ExtClassLoader去加载,⽽ExtClassLoader没有parent属性,所以会委派给BootstrapClassLoader去加 载,只有BootstrapClassLoader没有加载到,才会由ExtClassLoader去加载,也只有ExtClassLoader 没有加载到,才会由AppClassLoader来加载,这就是双亲委派。
双亲委派的优点:
- 避免类的重复加载,如果⼀个类被BootStrapClassLoader加载过了,那么AppClassLoader就不会 再重复加载到这个类了。
- 防⽌核⼼API被篡改,⾃定义⼀个java.lang.String类,但是我们是不到这个类的,因为根据双亲委派 始终加载的都是rt.jar中的java.lang.String类
后续写Tomcat为什么要⾃定义类加载器?运⾏时数据区