JVM面试(一) java虚拟机:双亲委派机制 的工作原理
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Mar
类的加载:
加载指的是将类的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被随意篡改
更多推荐
所有评论(0)