JVM虚拟机之双亲委派
本文源自Recently祝祝,创自Recently祝祝。转载请标注出处。
此解决方式在企业中有所应用,适合Java初级开发学习,参考。
本文字数与行数,耐心阅读必有收获。
1.什么是双亲委派机制?
主观理解:
当一个类加载器接收到类加载任务的时候,会先将这个类交给父类加载器加载,会先从类加载器先加载,如果没有找到,则会进入扩展类加载器加载,如果没有找到,则到应用加载器加载,最后自定义加载器,如果还是找不到该类,则会抛出ClassNotFoundException 异常。
父类无法加载,才会去子类找,然后加载该类。
简要理解:
.class文件首先会从应用程序类加载器进来,毕竟我们的项目就属于一个应用程序,而类的加载首先加载应用程序类加载器的父类加载器,在它的上边有两个类加载器,一个是启动类加载器、一个是扩展类加载器,类加载的顺序是从上到下加载,加载到应用程序类加载器还找到该类的情况下,才会去加载自定义类加载器。所以一开始类的加载就委派到了双亲那里去加载,所以称之为双亲委派机制。
也就是说当应用程序启动时,Application ClassLoader
会被创建并加入到虚拟机中。然后,它会根据指定的类路径来查找和加载应用程序所需的类文件。在类加载过程中,Application ClassLoader
会先委托其父类加载器(Extension ClassLoader
或Bootstrap ClassLoader
)来尝试加载类文件,如果父类加载器无法加载,那么就由Application ClassLoader
自己来加载。所以类加载的时候的双亲委派也就是先在父类加载器中寻找该类。
而我们自己开发的Java类编译成.class文件之后打成Jar包之后,最终也是由应用程序类来加载这些文件的。
根据上图可以做出判断。
2.为什么要进行双亲委派机制?
安全因素的趋势下,存在双亲委派机制。双亲委派可以避免一个类被重新加载,并且保证父类的完整性。在父类存在该类的情况下,父类就进行该类的加载,不需要在进行ClassLoader再次加载一次。
3.双亲委派机制源码:
作为一个Java程序员,你应该学会看点源码。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先, 检查class是否被加载,如果没有加载则进行加载
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;
}
}
当一个类被加载时,首先会检查该类是否已经被加载过了,如果已经被加载过了,那么直接返回该类;然后,先委托其父类加载器(父类加载器指的是当前类加载器的直接父类加载器)来尝试加载该类,父类加载器,没有加载到,则由当前类加载器,也就是应用程序加载类自己来加载该类。如果当前类加载器也无法加载该类,则会调用findClass方法来查找该类。最后,如果需要对该类进行解析(即将符号引用转换为直接引用),则会调用resolveClass方法进行解析。如果最终还是无法加载该类,则会抛出ClassNotFoundException异常。
类的加载中呢是,自底部向上检查该类是否被加载,加载了则返回,没有加载则继续往上寻找。如果找到启动类还是没有查找到该类被加载了。则会从启动类开始寻找改类进行加载。
图片做补充说明,文字有点长,但是看完整篇文章充分理解之后,那么双亲委派你就已经充分掌握了。
转载自:https://juejin.cn/post/7225218026097868856