搜索“ClassLoader”,然后打开“java.lang”包下的ClassLoader类。然后将代码翻到loadClass方法:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
// 查找该 class 是否已经被加载过
Class<?> c = findLoadedClass(name);
// 如果没有加载过
if (c == null) {
// 委托给父加载器去加载,递归调用
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 如果父加载器为空,查找 Bootstrap 是否加载过
c = findBootstrapClassOrNull(name);
}
// 若果依然加载不到,则调用自己的 findClass 去加载
if (c == null) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
protected Class<?> findClass(String name){
//1. 根据传入的类名 name,到在特定目录下去寻找类文件,把.class 文件读入内存
...
//2. 调用 defineClass 将字节数组转成 Class 对象
return defineClass(buf, off, len);
}
// 将字节码数组解析成一个 Class 对象,用 native 方法实现
protected final Class<?> defineClass(byte[] b, int off, int len){
...
}
这段代码已经很好的解释了双亲委派机制,一张图来描述一下上面这段代码的流程:
当类加载器收到一个类的加载请求时,首先会检查是否加载过,如果有就无须再加载了,如果没有将这个请求委派给父类加载器去加载,调用父加载器的loadClass方法。如果没有再往上,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。如果没有父类加载器,这时候会考虑自己是否能加载了,如果无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。