- 类加载 咱们都知道,JVM里通常有多个类加载器:
- 启动类加载器(加载rt.jar,且只负责这个范围,避免用户本身定义一个java.lang.Object类并加载),此类加载器没法被Java程序直接引用。
- 扩展类加载器 (加载 JAVA_HOME/lib/ext目录中的jar) ,能够直接使用。
- 应用程序类加载器 (负责加载ClassPath路径的类),经过ClassLoader.getSystemClassLoader()返回引用。
- 自定义的类加载器。
- JVM中类加载的顺序:若是一个类加载器收到了类加载请求,它先是把加载请求委派给父类加载器去完成,依次递归到启动类加载器。。。因此全部的加载请求最终都会传送到启动类加载器中去,但不必定会由启动类加载器完成加载(好比加载com.ali.Dog)。只有当父加载器没法完成该加载请求时(类加载器负责加载的范围找不到),子加载器才会去尝试加载。这个加载模型也称为“双亲委派加载模型”。
- 自定义类加载器 咱们为何须要自定义的类加载器?答:当你开发一个框架工具时,极可能要加载框架中的某些类。
- 如何定义本身的类加载器?首先你本身定义的类加载器,也要符合“双亲委派加载模型”。其次,你要理解ClassLoader类中的方法,推荐看源码。
- ClassLoader中的构造
- loadClass(String name, boolean resolve),第二个参数:是否在加载时linking。(链接是类加载步骤中的一步,是初始化的必要条件。即:类初始化了,一定通过链接。。而链接了,未必初始化了),补充一下类加载的流程:加载 -> (验证 -> 准备 -> 解析) -> 初始化 -> 使用 ->卸载。(验证 -> 准备 -> 解析 三个步骤合称链接),此方法的实现:a.查找是否加载过name类 b.若是没有加载过且有父加载器,则让父加载器去加载,若是没有父类加载器,则直接使用启动类加载器加载name类。c.若是通过上述两步,尚未加载到类name,那么再调用findClass(name)方法,此方法的ClassLoader类实现是抛出异常。。因此当你自定义一个类加载时,要复写该方法。
- defineClass(String name, byte[] b, int off, int len)方法,是用你本身类加载器实现“加载”这个动做的主要方法,我的感受,你确定不会真正的用C语言实现一下类加载的过程,无非是调用已有的“加载”方法。
- 《深刻理解Java虚拟机》 P228的代码demo分析,待续。。。有些困了,回头继续
[IBM wiki-Java虚拟机加载(https://www.ibm.com/developerworks/cn/java/j-lo-classloader/)java