委托模型
进入官方的Java doc里看到ClassLoader类的一段说明:
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
ClassLoader类使用一种委托模型来查找类和资源。每个ClassLoader实例都会关联1个父ClassLoader。当需要查询类和资源的时候,一个ClassLoader实例在查询类或资源之前会先委托给它的父ClassLoader去查询。Bootstrap ClassLoader是最顶层的加载器,并且可以作为其它ClassLoader实例的父ClassLoader。
由此看见,这个“委托模型”的安全性是很高的,Bootstrap是最顶层的加载器,这样比如加载 java.lang.String 的时候,永远都会被Bootstrap加载(Bootstrap ClassLoader会加载%JAVA_HOME%/jre/lib中rt.jar里的String类)。 这样用户自定义的java.lang.String永远都不会被加载,这样就避免了多个java.lang.String造成的混乱现象。
下面通过jdk里的ClassLoader源码来验证一下查找过程:
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name); //先查找这个类是否已经加载过,每个加载器都有自己的缓存
if (c == null) {
try {
if (parent != null) { //父加载器存在的话先使用父加载器加载
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name); //没有父加载器的话使用bootstrap加载
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name); //如果父加载器没有找到,那么自身查找
}
}
if (resolve) {
resolveClass(c);
}
return c;
}