自底向上检查是否已装载,自顶向下尝试加载类
-
例(加载A.class)
-
首先先检查 Custom(自定义) ClassLoader,有则返回,否则继续向上寻找,App ClassLoader --> Ext ClassLoader --> BootStrap ClassLoader 在哪一个加载器找到,就在那个加载器返回。
若都没有装载,则从BootStrap ClassLoader 开始到相应目录下寻找。
Xbootclasspath:指定BootStrap ClassLoader管理的目录,在java -jar xxx.jar 时可以制定。
JAVA 实现代码:
/**
* loderClass 类
* @param resolve:如果为true 则解析类
*/
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
/** 同步锁,为了防止多个线程调用同一个线程,加载其他类 */
synchronized (getClassLoadingLock(name)) {
/** 首先,检查类是否已经加载过,这个类 */
Class<?> c = findLoadedClass(name);
/** 如果没加载 */
if (c == null) {
long t0 = System.nanoTime();
try {
/**
* 查看parent是否为空
* 例如:Coustom classLoader 的 parent为:App ClassLoader,如上图所示
*/
if (parent != null) {
/**
* parent不为空,调用上级的:loadClass方法
*/
c = parent.loadClass(name, false);
} else {
/** Ext ClassLoader调用 parent.loadClass时会进入,因为BootStrap ClassLoader为C++ 代码 */
/** 此函数会调用一个 native 方法 */
/** 返回由引导类装入器加载的类,如果找不到,则返回null */
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
/**
* 如果上层没有找到,则进入此处 If
*/
if (c == null) {
long t1 = System.nanoTime();
/** 调用findClass,在对应的路径寻找类 */
/** 有则返回,没有继续返回,进入此处尝试寻找 */
c = findClass(name);
// 这是定义类装入器,记录统计信息
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
/** 如果加载过,则直接返回 */
return c;
/** 如果最终没有则抛出:ClassNotFoundException */
}
为什么使用双亲委派机制去加载类:
避免多份同样字节码的加载