初探JVM02
初探JVM02 -双亲委派机制
(博客来自本人csdn原创)
什么是双亲委派机制:
当某个类加载器要加载一个.class
文件时候,它首先把这个请求委托给父加载器去完成,一直向上委托,递归操作,如果上级的类加载器没有加载 ,它就自己加载,直到启动类加载器;
代码测试:
- String 默认情况下是启动类加载器进行加载的,假设我也自定义一个 String。你会发现自定义的String 可以正常编译,但是无法被加载运行。
- 这是因为申请自定义String加载时,总是启动类加载器,而不是自定义类加载器,也不会是其他的类加载器。
- 双亲委派机制可以确保Java核心库所提供的类,不会被自定义的类所替代。
来看一下Java执行代码的相关流程
假设要执行A类的main方法
-
启动虚拟机 (c++负责创建)
-
创建一个引导类加载器实例(c++实现)
-
C++调用Java代码,创建JVM启动器,实现sun.misc.Launcher
查看源代码快捷键是 crtrl+鼠标左键
查看一个类的全部方法是 alt+7
- sun.misc.Launcher.getLauncher() 获取运行类自己的加载器ClassLoader -->是AppClassLoader,通过上图源码可知
5.获取到ClassLoader 后调用loadClass("A") 方法加载运行的类A
6.加载完成执行A类的main方法
7.程序运行结束
8.JVM销毁
Launcher构造函数
,我们看一下它的构造函数干了什么
-
Launcher构造方法内部,创建了两个类加载器,分别是sun.misc.Launcher.ExtClassLoader(扩展类加载器)和sun.misc.Launcher.AppClassLoader(应用类加载器)
-
JVM 默认使用Launcher的getClassLoader()方法返回的类加载器AppClassLoader来加载我们的应用程序。
源码解析ClassLoader&loaderClass
loadClass实现了双亲委派的功能,我们有必要深入了解一下
既然都是向上委托向上查找,我们来看一下应用程序类加载器AppClassLoader加载类的双亲委派机制源码,AppClassLoader的loadClass的方法最终会调用其父类的ClassLoader的loadClass方法
/*
一些注释就不添加了!懒!
*/
- 首先,检查一下指定名称的类是否加载过,如果加载过,就不需要再加载,直接返回。
- 如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用parent.loadClass(name,false);)或者是调用根(Bootstrap)类加载器加载
- 如果父加载器及BootStrap类加载器都没有找到指定的类,那么调用当前类加载器的findClass方法【调用URLClassLoader的findClass 方法在加载器的类路径里查找并加载此类】来完成加载。
双亲委派机制的优点
1:沙箱安全机制:表现为自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改
2.避免类的重复加载,当父类已经加载了此类,就没必要再加载一次。保证了加载类的唯一性!