前言
看大部分博客讲到类加载器时都会讲一堆理论,稍显枯燥,今天我就来带大家玩点好玩的,手动加入拓展类,看看是不是真的是由扩展类加载器所加载?
类加载器
- Bootstrap ClassLoader(启动类加载器)负责将%JAVA_HOME%/lib目录中或-Xbootclasspath中参数指定的路径中的,并且是虚拟机识别的(按名称)类库加载到JVM中
- Extension ClassLoader(扩展类加载器)负责加载%JAVA_HOME%/lib/ext中的所有类库
- Application ClassLoader(应用程序加载器) 负责ClassPath中的类库,就是用户定义的类
扩展类加载器
package bingo;
public class Bingo {
public static void main(String[] args) {
System.out.println("关注J2彬彬");
}
}
ext文件夹就是JDK存放扩展类的地方,将上面这段代码编译成class文件,放到下图的的bingo文件夹下
下面是个简单的案例
package com.bingo.classloader;
import bingo.Bingo;
public class ClassLoaderTest {
public static void main(String[] args) {
Object object = new Object();
System.out.println("object加载器:"+object.getClass().getClassLoader());
Bingo bingo = new Bingo();
System.out.println("bingo加载器:"+bingo.getClass().getClassLoader());
System.out.println("bingo加载器的父类:"+bingo.getClass().getClassLoader().getParent());
ClassLoaderTest test = new ClassLoaderTest();
System.out.println("test加载器:"+test.getClass().getClassLoader());
System.out.println("test加载器的父类:"+test.getClass().getClassLoader().getParent());
System.out.println("test加载器的父类的父类:"+test.getClass().getClassLoader().getParent().getParent());
}
}
执行结果:
object加载器:null
bingo加载器:sun.misc.Launcher$ExtClassLoader@29453f44
bingo加载器的父类:null
test加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
test加载器的父类:sun.misc.Launcher$ExtClassLoader@29453f44
test加载器的父类的父类:null
双亲委派模型
由执行结果可以看出,Bingo类由ExtClassLoader加载,用户自定义的类一般都是由AppClassLoader加载,而Object类在rt.jar下,由Bootstrap加载器加载,它是由C++实现的,所以打印结果为null。getParent()得到父类加载器,这里就可以看出双亲委派模型。
为什么要加载类需要委托双亲加载呢?
- 每一个类都只会被加载一次,避免了重复加载
- 每一个类都会被尽可能的加载(从引导类加载器往下,每个加载器都可能会根据优先次序尝试加载它)
- 有效避免了某些恶意类的加载(比如自定义了Java。lang.Object类,一般而言在双亲委派模型下会加载系统的Object类而不是自定义的Object类)
我是广州的java程序员小彬,一直在致力于java后端的学习,下面是我的微信公众号,里面有更多有质量的文章,感谢大家!