https://www.cnblogs.com/faunjoe88/p/8023239.html
1、首先一个AppClassLoader 查找资源时,先看缓存里有没有,如果有就从缓存中获取,否则就委托父类加载器
2、如果父类ExtClassLoader 没有加载过,则有BootClassLoader出面,首先它先查询缓存,如果没有找到的话 就从自己的路径下找 也就是“sun.mic.boot.class”路径下 如果找到就返回,没有找到就就让子类加载器自己找,
3、BootClassLoader如果没有找成功,则ExtClassLoader在自己的路径下找“java.ext.dirs”中路径中查找,如果没找到则由子类加载器自己找
4、ExtClassLoader 如果找不成功,则由AppClassLoader自己查找的路径下找“java.class.path”找,找到返回,找不到就包异常
详细介绍了加载过程
首先我们需要了解几个重要的方法,LoadClass();findLoadedClass();findClass();defineClass();
1、loadClass方法步骤
(1)、首先执行findLoadedClass(String name)方法 是否类已被加载过了
(2)、执行父类的执行方法loaderClass()如果父类为空,责使用jvm的内置类加载器 也就是bootStrapClassLoader 也就解释ExtClassLoader的父类parent 为空null,但让然说bootStarpClassLoader是的它的父加载器
(3)、如果向上委托父类没有成功,则执行findClass方法去查找,如果上述步骤找到类,则resolve参数为true,那么loadClass方法又会调用resolveClass方法最终生成对象。
补充问题: ExtClassLoader的parent为null,但仍然说Bootstrap ClassLoader是它的父加载器
答:因为源码中loadclass()方法 首先调用findLoadedClass 是否已经被加载过 ,然后调用父类方法loadClass方法,如果父类为空。则调用jvm内置类加载加器 bootstrapClassLoader
执行父加载器的loadClass方法。如果父加载器为null,则jvm内置的加载器去替代,也就是Bootstrap ClassLoader。这也解释了ExtClassLoader的parent为null,但仍然说Bootstrap ClassLoader是它的父加载器
Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,所以在java程序代码里试图打印出其内容时,我们就会看到输出为null。
在java中类装载器把一个类装入JVM,经过以下步骤:
1.装载查找和导入class文件 2、衔接其中的步骤可以选择的 a.检查载入的class文件的正确性,b.准备 给类和静态变量分配空间 c.将符号引用转为直接引用,d.初始化对静态变量,静态代码块初始化工作
2.自定义ClassLoader 首先我们在findClass方法中定义了查找class的方法,然后数据通过defineClass生成了class对象
综合上述关键字 就是路径
BootStrap ClassLoader、ExtClassLoader、AppClassLoader 都是指定路径下jar文件
JVM类加载机制
•全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
•父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
•缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效
Class.forName()和ClassLoader.loadClass()区别
Class.forName():将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块;
ClassLoader.loadClass():只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
注:
Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
双亲委派模型
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
双亲委派机制:
1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
双亲委派的意义:
--系统类防止内存中存在多份同样的字节码
--保证java程序安全稳定运行
网友评论