学习JVM的一点简单笔记,宋红康老师jvm讲的很好,感谢。
尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机)
双亲委派机制
双亲委派机制:避免类的重复加载,保护程序安全,防止核心api被随意篡改。
假如定义一个自己创建java.lang的包,下面定义一个String类。
package java.lang;
/**
* @Author: 秃头不用洗发水
* @Date: 2021-02-19
* @Description:
*/
public class String {
static{
System.out.println("自定义的java.lang.String");
}
}
测试一下这个类。
package com.hut.djh;
/**
* @Author: 秃头不用洗发水
* @Date: 2021-02-19
* @Description:
*/
public class Test2 {
public static void main(String[] args) {
java.lang.String str = new java.lang.String();
System.out.println("这是Test2");
ClassLoader classLoader = str.getClass().getClassLoader();
System.out.println(classLoader);//null,系统核心类库使用启动类加载器bootstrap ClassLoader
}
}
发现String类并没有被加载。——>双亲委派机制。
所以在刚刚的代码中,new java.lang.String 这个new的是核心api的String类,被bootstrap classloader加载,而不是自定义的String类,类只会被一个加载器加载。
报错,核心api String 没有main方法的,所以就是根本没有试图加载我们自定义的String类,直接忽略了。
目的:保持加载行为可控,避免类的重复加载,保护程序安全,防止核心api被随意篡改(万一有恶意发送一些和核心类同名同包的文件,例如这里的自定义的java.lang.String类),采取双亲委派机制。一个类只会由一个类加载器加载,默认使用系统类加载器(Application ClassLoader)。
类加载器不会先自己加载,而是向上委托,请求委托父类加载器,进一步向上委托直至bootstrap classloader,如果父类加载器可以完成加载,就成功返回。若无法加载,子加载器自己尝试加载。最终会使用application classloader(不会无加载器可用)
例子:假如三级加载器为 儿子-application 、母亲-extension、奶奶-bootstrap 三代,那么假如,加载 == 有个苹果,儿子就会拿着苹果 给母亲,母亲会拿着苹果给奶奶。如果奶奶吃苹果,那么就结束,不吃就给妈妈,妈妈不吃就给儿子吃。苹果只有一个,类只会由一个加载器加载。
接口是由bootstrap classloader 加载,具体接口的实现类是由application classloader
也不允许在核心类库例如java.lang随意创建类(安全考虑)
java.lang.SecurityException: Prohibited package name: java.lang
双亲委派机制:避免类的重复加载,保护程序安全,防止核心api被随意篡改。