为什么有这样的机制
双亲委派,主要出于jvm的安全来考虑, 同时也实现了类只加载一次,加载过的类就不能再加载和修改了
类加载流程
在理解类加载的过程的时候先说几个点
- 检查自己是否有加载过类 > 这个的意思可以理解成为每个加载器都有一个自己的缓存,在加载类的过程中时候先去缓存中查询是否存在。
(这部分的代码缓存的代码不是java实现的)
- 可以理解为每个类加载器可以理解为有两个重要的方法一个方法是查找缓存中是否有该类, 第二个方法是查找自己对应的路径下是否有该类
- 父加载器 > 这里的父加载器我刚接触的时候弄混了, 这里的父加载器并不是java 中的父类, 和java中说的父类没任何关系,甚至AppClassLoader和ExtClassLoader 在java 代码中都是同级的,都继承了URLClassLoader,两个都是Launcher 类的内部类
类加载过程
- 首先查询缓存,先是之下而上查找从 自定义类加载器 —>AppClassLoader —> ExtClassLoader —> Bootstrap 按照这个顺序查询加载器缓存中是否存,
- 如果查询到Bootstrap 缓存中也没有的时候, 那Bootstrap 就会去他对应的路径下去查询是否存在该类, 如果没有就会让ExtClassLoader 去他的指定路径下加载,以此类推直到自定义加载器都没有的情况就会报ClassNotFoundException异常
代码位置:
- AppClassLoader是Launcher类的一个内部类, AppClassLoade继承了URLClassLoader而URLClassLoader中重写了findClass,所以在ClassLoader类中的loadClass方法里面调用findClass实际执行的是URLClassLoader类中的findClass(这里也是利用了java 子类重写父类方法,调用时会调用子类重写之后的方法)
- 查询缓存中是否有加载过的方法实际是调用本地方法
findLoadedClass0
- 根据类权限命名去指定位置查询的方法最终实际是本地方法
defineClass1
- 最顶级的父加载器bootstrap他实际调用的是本地方法
findBootstrapClass