Java虚拟机 双亲委派机制 的工作原理
类的加载:
加载指的是将类的class文件读入到内存,并为之创建一个java.lang.Class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象。
类的加载由类加载器完成,类加载器通常由JVM提供,这些类加载器也是前面所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过继承ClassLoader基类来创建自己的类加载器。
双亲委派机制 的工作原理
1)如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行。
2)如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归请求最终将到达顶层的启动类加载器。
3)如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
案例举例:
下面我们不妨通过一个例子来帮助我们理解一下双亲委派机制:
首先我们在工程下创建一个java.lang包,包下新建一个String类(我们在此只做示范,实际代码中不推荐同学们以此命名)
在String类中加入以下代码:
package java.lang;
public class String {
static {
System.out.println("我是java.lang包下的String类");
}
}
我们可以将其看成一个我们手写的一个”伪装“的String类
接着我们在工程的另一个包下新建一个StringTest类
其中加入以下方法:
package Test;
public class StringTest {
public static void main(String[] args) {
String str=new java.lang.String();
System.out.println("开始测试。。。");
}
}
那么问题来了,当我们new java.lang包下的String类时,我们new的是java系统包下的String呢还是我们刚刚自己定义的String类呢?
换言之,我们在上面定义的String类中加入的static静态代码块会不会执行呢??
请看运行结果:
很显然,static静态代码块并没有执行,我们new 的String类仍是系统包下的String类。
案例解析:
这便是双亲委派机制的完美体现。很好保证了我们系统核心API不容易被破坏。
当我们new String时,我们自己创建的String类应当由系统类加载器(应用程序类加载器)来加载,但根据双亲委派机制,系统类加载器会先委托给它的父类加载器(拓展类加载器)去加载,如果拓展类加载器仍存在父类则继续向上委托。
我们 new String时向上委托会被引导类加载器(BootStap ClassLoader)所加载,所以我们new 出的String便是我们核心API中的String类,即不会再new我们自己创建的String类。
双亲委派机制的优势:
1)避免类的重复加载
2)保护程序安全,防止核心API被随意篡改