JVM-双亲委派机制详解以及实例代码验证
提示:以下是本篇文章正文内容,下面案例可供参考
一、双亲委派机制是什么?
双亲委派机制是JVM加载类的一种设计机制
二、双亲委派机制详细加载顺序
要理解双亲委派机制,我们首先要知道几个类加载器的类型
1.引导性类加载器(C++实现)
2.扩展性类加载器(JAVA实现)
3.应用类加载器(JAVA实现)
4.自定义类加载器(JAVA实现)
二、各个类加载器加载的范围是什么
import sun.misc.Launcher;
import java.net.URL;
public class testMyClassLoader {
public static void main(String[] args) {
System.out.println(String.class.getClassLoader());//运行结果为null 因为String类位于rt.jar(java运行核心类库)下面,由引导类加载器负责加载,引导类加载器是C++实现的 故该部分为Null
System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName());//这个是
System.out.println(testMyClassLoader.class.getClassLoader());//这个是开发自己创建的类,由应用类加载器负责加载
System.out.println();
ClassLoader appClassLoader = testMyClassLoader.class.getClassLoader();//获取到应用类加载器
System.out.println(appClassLoader);
System.out.println(appClassLoader.getParent());
System.out.println(appClassLoader.getParent().getParent());
//此时可以看出来类加载器的顺序是 应用类加载器->扩展类加载器->引导类加载器(这部分打印为null 也是因为该部分为C++实现)
System.out.println();
System.out.println("引导类加载器加载文件");
URL[] urls = Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i < urls.length; i++) {
System.out.println(urls[i]);//打印引导类加载器 加载的文件范围 jre/lib下的核心类库
}
System.out.println("扩展类加载器加载的文件");
System.out.println(System.getProperty("java.ext.dirs"));//扩展类加载器加载的文件
System.out.println("appClassLoader加载以下文件");
System.out.println(System.getProperty("java.class.path"));//appClassLoader加载以下文件 java.class.path是jar运行时路径
}
}
运行结果:
tips:
1.可以看到应用类加载器加载的范围,包括了扩展类加载器和引导类加载器,但是实际他只会加载当前的项目的jar运行项目下面的类
2.虽然parent方法依次从应用类加载器指向引导类加载器,但是他们并不是父子继承关系,只是方法调用关系,接下来会深入源码剖析
三、剖析双亲委派机制源码
全局搜索到Laucher类
这里先创建了一个扩展类加载器val1,作为变量传入方法
下钻方法
最后定位到 parent只是一个成员变量,故解答了,应用类加载器和扩展类加载器是调用关系,而不是继承关系
扩展类加载器可以自行下钻对应的方法,这里展示下钻最后一步,最后传入的变量为null,因引导类加载器为C++实现
上面的步骤大概了解了几个类加载器之间的调用关系,现在看核心源码
四、为什么要设计双亲委派机制?
1.沙箱机制:保证java的核心类库不会被后面开发的类给覆盖,或者在核心类库植入后门程序
2.性能考虑:避免类被重复加载,保证类加载的唯一性
package java.lang;
public class String {
public static void main(String[] args) {
System.out.println("**************My String Class**************");
}
}
五、总结
这里类加载其实就有一个双亲委派机制,加载某个类时会先委托父加载器寻找目标类,找不到再
委托上层父加载器加载,如果所有父加载器在自己的加载类路径下都找不到目标类,则在自己的
类加载路径中查找并载入目标类。
比如我们的Math类,最先会找应用程序类加载器加载,应用程序类加载器会先委托扩展类加载
器加载,扩展类加载器再委托引导类加载器,顶层引导类加载器在自己的类加载路径里找了半天
没找到Math类,则向下退回加载Math类的请求,扩展类加载器收到回复就自己加载,在自己的
类加载路径里找了半天也没找到Math类,又向下退回Math类的加载请求给应用程序类加载器,
应用程序类加载器于是在自己的类加载路径里找Math类,结果找到了就自己加载了。。
双亲委派机制说简单点就是,先找父亲加载,不行再由儿子自己加载