Java自带三种“类加载器”,分别用于加载不同路径下的类文件。
System.out.println("BootClassLoader:" + System.getProperty("sun.boot.class.path"));
System.out.println("ExtClassLoader:" + System.getProperty("java.ext.dirs"));
System.out.println("AppClassLoader:" + System.getProperty("java.class.path"));
BootClassLoader:
jdk1.8.0_202jrelibresources.jar;jdk1.8.0_202jrelibrt.jar;jdk1.8.0_202jrelibsunrsasign.jar;jdk1.8.0_202jrelibjsse.jar;jdk1.8.0_202jrelibjce.jar;jdk1.8.0_202jrelibcharsets.jar;jdk1.8.0_202jrelibjfr.jar;jdk1.8.0_202jreclasses
ExtClassLoader:jdk1.8.0_202jrelibext;C:WindowsSunJavalibext
AppClassLoader:jdk1.8.0_202jrelibcharsets.jar;jdk1.8.0_202jrelibdeploy.jar;jdk1.8.0_202jrelibextaccess-bridge-64.jar;jdk1.8.0_202jrelibextcldrdata.jar;jdk1.8.0_202jrelibextdnsns.jar;jdk1.8.0_202jrelibextjaccess.jar;jdk1.8.0_202jrelibextjfxrt.jar;jdk1.8.0_202jrelibextlocaledata.jar;jdk1.8.0_202jrelibextnashorn.jar;jdk1.8.0_202jrelibextsunec.jar;jdk1.8.0_202jrelibextsunjce_provider.jar;jdk1.8.0_202jrelibextsunmscapi.jar;jdk1.8.0_202jrelibextsunpkcs11.jar;jdk1.8.0_202jrelibextzipfs.jar;jdk1.8.0_202jrelibjavaws.jar;jdk1.8.0_202jrelibjce.jar;jdk1.8.0_202jrelibjfr.jar;jdk1.8.0_202jrelibjfxswt.jar;jdk1.8.0_202jrelibjsse.jar;jdk1.8.0_202jrelibmanagement-agent.jar;jdk1.8.0_202jrelibplugin.jar;jdk1.8.0_202jrelibresources.jar;jdk1.8.0_202jrelibrt.jar;D:2-CodeRepocoderwwtargetclasses;D:Program FilesIntelliJ IDEA Community Edition 2021.2.2libidea_rt.jar
二、类加载器的关系阅读Launcher类代码:
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
ExtClassLoader是AppClassLoader的parent,他们之间不存在类的继承关系。
BootClassLoader与ExtClassLoader、AppClassLoader则没有parent或者继承关系。
三、类的加载顺序阅读抽象类ClassLoader代码:
protected Class> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 步骤1
// First, check if the class has already been loaded
Class> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
// 步骤2
c = parent.loadClass(name, false);
} else {
// 步骤3
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// 步骤4
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
步骤1:首先由当前“类加载器”查找是否已经加载过该类名;
步骤2:如果没有查找到,且parent“类加载器”非空,则由parent“类加载器”尝试加载该类;
步骤3:如果没有查找到,且parent“类加载器”为空,则由BootClassLoader“类加载器”尝试加载该类;
步骤4:如果parent“类加载器”或者BootClassLoader“类加载器”都未能加载该类,则由当前“类加载器”尝试加载;AppClassLoader和ExtClassLoader的类加载方式由共同“父类”URLClassLoader实现,具体参考findClass方法。
四、自定义类加载器1.自定义类加载器构造函数为空时,parent类加载器是AppClassLoader,由父类ClassLoader的空构造函数实现,详见getSystemClassLoader;
2.自定义类加载器实现findClass方法,用来加载指定目录下的类文件,可以参考URLClassLoader的findClass实现方法;



