此文已由作者赵计刚薪授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
1、ClassLoader作用
2、类加载器结构
结构:BootstrapClassLoader(祖父)-->ExtClassLoader(爷爷)-->AppClassLoader(也称为SystemClassLoader)(爸爸)-->自定义类加载器(儿子)
关系:看括号中的排位;彼此相邻的两个为父子关系,前为父,后为子
2.1、BootstrapClassLoader
2.2、ExtClassLoader:
2.3、AppClassLoader:
2.4、自定义类加载器:
3、全盘负责机制
概念:假设ClassLoaderA要加载class B,但是B引用了class C,那么ClassLoaderA先要加载C,再加载B,"全盘"的意思就是,加载B的类加载器A,也会加载B所引用的类
4、双亲委托机制
这也是类加载器加载一个类的整个过程。
过程:假设我现在从类路径下加载一个类A,
1)那么app会先查找是否加载过A,若有,直接返回;
2)若没有,去ext检查是否加载过A,若有,直接返回;
3)若没有,去boot检查是否加载过A,若有,直接返回;
4)若没有,那就boot加载,若在E:\Java\jdk1.6\jre\lib\*.jar下找到了指定名称的类,则加载,结束;
5)若没找到,boot加载失败;
6)ext开始加载,若在E:\Java\jdk1.6\jre\lib\ext\*.jar下找到了指定名称的类,则加载,结束;
7)若没找到,ext加载失败;
8)app加载,若在类路径下找到了指定名称的类,则加载,结束;
9)若没有找到,抛出异常ClassNotFoundException
注意:
总结:
5、源代码
1 /** 2 * 根据指定的binary name加载class。 3 * 步驟: 4 * 假设我现在从类路径下加载一个类A, 5 * 1)那么app会先查找是否加载过A(findLoadedClass(name)),若有,直接返回; 6 * 2)若没有,去ext检查是否加载过A(parent.loadClass(name, false)),若有,直接返回; 7 * findBootstrapClassOrNull(name) 3)4)5)都是这个方法 8 * 3)若没有,去boot检查是否加载过A,若有,直接返回; 9 * 4)若没有,那就boot加载,若在E:\Java\jdk1.6\jre\lib\*.jar下找到了指定名称的类,则加载,结束; 10 * 5)若没找到,boot加载失败; 11 * findClass(name) 6)7)8)9)都是这个方法 12 * 在findClass中调用了defineClass方法,该方法会生成当前类的java.lang.Class对象 13 * 6)ext开始加载,若在E:\Java\jdk1.6\jre\lib\ext\*.jar下找到了指定名称的类,则加载,结束; 14 * 7)若没找到,ext加载失败; 15 * 8)app加载,若在类路径下找到了指定名称的类,则加载,结束; 16 * 9)若没有找到,抛出异常ClassNotFoundException 17 * 注意:在上述过程中的1)2)3)4)6)8)后边,都要去判断是否需要进行"解析"过程 18 */ 19 protected synchronized Class<?> loadClass(String name, boolean resolve) 20 throws ClassNotFoundException { 21 Class c = findLoadedClass(name);//检查要加载的类是不是已经被加载了 22 if (c == null) {//没有被加载过 23 try { 24 if (parent != null) { 25 //如果父加载器不是boot,递归调用loadClass(name, false) 26 c = parent.loadClass(name, false); 27 } else {//父加载器是boot 28 /* 29 * 返回一个由boot加载过的类;3) 30 * 若没有,就去试着在E:\Java\jdk1.6\jre\lib\*.jar下查找 4) 31 * 若在bootstrap class loader的查找范围内没有查找到该类,则返回null 5) 32 */ 33 c = findBootstrapClassOrNull(name); 34 } 35 } catch (ClassNotFoundException e) { 36 //父类加载器无法完成加载请求 37 } 38 if (c == null) { 39 //如果父类加载器未找到,再调用本身(这个本身包括ext和app)的findClass(name)来查找类 40 c = findClass(name); 41 } 42 } 43 if (resolve) { 44 resolveClass(c); 45 } 46 return c; 47 }
说明:
附:关于递归
递归基于栈实现。
上述的代码如果不清楚递归的意义是看不清的。
解释:
这样,就完成了双亲委托机制。
递归太烦了,实际开发中尽量不要用!
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请点击。