类加载器和双亲委派机制
JVM中提供了三层的ClassLoader:
Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
ExtClassLoader:扩展类加载器 主要负责加载jre/lib/ext目录下的一些扩展的jar。
AppClassLoader:主要负责加载应用程序的主函数类
类加载器
编译后的字节码文件首先由类加载器对其进行初始化,加载生成Class模板,使用new对模板进行实例化,实例化的对象保存在堆内存中,栈内存保存对对象的引用(即地址)。对象可以通过 getClass() 方法得到模板,在进行 getClassLoader得到类加载器。
对象可以通过 getClass() 方法得到的模板 Hello Class是同一个。
双亲委派机制
Hello.class进入虚拟机后,首先被类加载器进行加载,类加载采用了双亲委派机制。为了避免重复加载造成的资源浪费,因此每次加载前都会首先判断其是否已经被加载过。
首先进入AppClassLoader检查其是否被加载过,如果类被加载了就不在加载,否则进入上一级加载器ExtClassLoader检查是否被加载,如果类被加载了就不在加载,否则进入上一级加载器Bootstrap classLoader,如果类被加载了就不在加载;否则由Bootstrap classLoader首先查看其是否有对应的类加载器,如果有就会由Bootstrap classLoader进行加载;如果没有就会进入下一级ExtClassLoader,查看其是否有对应的类加载器,如果有就会由ExtClassLoader进行加载;如果没有就会进入下一级AppClassLoader,查看其是否有对应的类加载器,如果有就会由AppClassLoader进行加载;如果没有就会抛出ClassNotFoundException异常
图片来源:https://blog.youkuaiyun.com/codeyanbao/article/details/82875064
ExtClassLoader:扩展类加载器 主要负责加载jre/lib/ext目录下的一些扩展的jar。
采用双亲委派机制的好处
①**防止加载同一个.class。**通过委托去询问上级是否已经加载过该.class,如果加载过了,则不需要重新加载。保证了数据安全,也减少了性能开销;
②**保证核心.class不被篡改。**通过双亲委托的方式,保证核心.class不被篡改,即使被篡改也不会被加载,即使被加载也不会是同一个class对象,因为不同的加载器加载同一个.class也不是同一个Class对象。这样则保证了Class的执行安全。在这种机制下系统的类已经被Bootstrap classLoader加载过了(因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,一定程度上保证了核心.class的安全。