前面我们知道类的加载均是由 ClassLoader 加载进入内存的,那么这里类的加载有没有三六九等呢?加入我自己定义一个 java.lang.String 类,偷偷摸摸的写一些代码,去坑别人迷惑别人可以吗?
- 答案是不可以的,这种
安全问题不会出现,原因就是 jvm 加载类的时候有双亲委派机制。
- Java 虚拟机对 Class 文件采用的是按需加载的方式
- 也就是说当需要使用该类时才会将它的 class 文件加载到内存生成 Class 对象。
- 而且加载某个类的 class 文件时, Java 虚拟机采用的是双亲委派模式
- 即把请求交由父类类处理, 它是一种任务委派模式。
工作原理:
- 如果一个类加载器收到了类加载请求, 它并不会自己先去加载, 而是把这个请求委托给父类的加载器去执行;
- 如果父类加载器还存在其父类加载器, 则进一步向上委托, 依次递归。请求最终将到达顶层的启动类加载器;
- 如果父类加载器可以完成类加载任务, 就成功返回, 倘若父类加载器无法完成此加载任务, 子加载器才会尝试自己去加载, 这就是双亲委派模式。
家里穷买了一个杨桃
- 小孙子小明先拿到,想吃呢?一看爸爸在,就给了爸爸,说爸爸,你吃吧
- 小明爸爸结果杨桃正想吃呢,想到了孩子的爷爷还没吃呢,转手就递给了小明爷爷,说爸爸,你吃吧。
- 小明爷爷结果杨桃,一看这么新鲜,舍不得吃,递给了自己儿子,说儿子,你吃吧。
- 小明爸爸接过杨桃,一看,觉得还是让小明吃好,就递给了小明。
- 小明结果杨桃,高兴的吃了起来。
看见了吧
杨桃就是要加载的类
只要爸爸和爷爷任何人想吃杨桃,就轮不到小明了。
- AppClassLoader 接过任务,要加载,一看爸爸 ExtClassLoader 在,就交给了爸爸 ExtClassLoader。
- ExtClassLoader 结果任务,要加载,一看爸爸 BootStrapClassLoader 在,就交给了爸爸 BootStrapClassLoader。
- BootStrapClassLoader 一看这个类确实在自己的负责范围之内。就记载了。
这样就算程序员故意写一个 java.lang.String 也没法加载,因为爷爷要先加载,且加载自己负责的一亩三分地里的 java.lang.String。而不是程序员定义的 java.lang.String, 因为程序员定义的 java.lang.String 不在 bootStrapClassLoader 职责范围之内。
java.lang.StringSSS 这个类很特殊。程序员够狠,定义了一个不存在的类。
- AppClassLoader 接过任务,要加载,一看爸爸 ExtClassLoader 在,就交给了爸爸 ExtClassLoader。
- ExtClassLoader 结果任务,要加载,一看爸爸 BootStrapClassLoader 在,就交给了爸爸 BootStrapClassLoader。
- BootStrapClassLoader 一看这个类要加载,先在自己的职责范围内找了一圈发现没有,这个类,就把加载全给了 ExtClassLoader,说你加载吧,我这里没有这个类
- 此时 ExtClassLoader 拿到这个类后,才有资格去查一下自己的职责范围内有么有这个类,第一次拿到的时候必须先让给他爸爸,连查找一下都不行。于是查找了一圈发现没有,就把加载权给了 AppClassLoader
- AppClassLoader 结果权限后,一查,果然在,就加载了。
这个过程就是这样,这就是双亲委派机制。
双亲委派就是子 -> 爸 -> 爷;然后爷 -> 爸 -> 子的过程这两圈就叫双亲委派。别误会啊。不是别的双亲委派。
那么上文说达到的各个类加载器的责任范围是什么呢?且听下回分解!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!