一、双亲委派作用
保证每个加载的类在jvm中保持唯一性,也保证系统类(例如Integer,String)在加载时不被串改
二、双亲委派原理
jvm提供三种加载器:
- 启动类加载器(Bootstrap ClassLoader)
C++实现,在java里无法获取,负责加载<JAVA_HOME>/lib下的类。 - 扩展类加载器(Extension ClassLoader)
Java实现,可以在java里获取,负责加载<JAVA_HOME>/lib/ext下的类。 - 系统类加载器/应用程序类加载器(Application ClassLoader)
是与我们接触对多的类加载器,我们写的代码默认就是由它来加载,即classPath目录,ClassLoader.getSystemClassLoader返回的就是它。
加载流程:
- 子类委托给父类加载
- 父类在自己加载范围内,如果都无法加载则返回给子类自己加载,自己不加载
- 父类未加载则子类进行自己加载
代码实现:
采用递归形式进行父级加载
java.lang.ClassLoader
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
//验证类是否已经加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
//递归父类委派
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} 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.
long t1 = System.nanoTime();
//父类未加载则子类进行加载
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
实现自己的类加载器继承ClassLoader在重写findClass方法即可