|
基本概述
简单说,类加载器就是根据指定名称将class文件加载到JVM内存,转为Class对象。
根(Bootstrap)类加载器:
没有继承java.lang.ClassLoader类。
Bootstrp加载器是用C++语言实现,它是在Java虚拟机启动后初始化的,属于虚拟机的实现的一部分。它主要负责加载核心类库。例如java.lang.Object ;%JAVA_HOME%/jre/lib。
扩展(Extension)类加载器:
由Java语言实现,继承自抽象类ClassLoader。
ExtClassLoader主要负责加载<JAVA_HOME>\lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。如果把用户创建的JAR文件放在这个目录下,也会自动由扩展类加载器加载。
系统(System)类加载器:
由Java语言实现,继承自抽象类ClassLoader。
负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
所谓的父子加载器并非继承关系,也就是说子加载器不一定是继承了父加载器。只是在构造函数中传入某个加载器,它被指定为父加载器。
ClassLoader加载过程
<hr>双亲委派机制的工作流程:
1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。
每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了。
2. 当前classLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到bootstrp ClassLoader.
3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。
<hr>使用双亲委托模式的好处
1. 可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
2. 考虑到安全因素,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoader。
<hr>双亲委派模型是否可以被破坏?
可以继承java.lang.ClassLoader类,实现自己的类加载器。
如果想破坏双亲委派模型,可以重写loadClass(name)方法。重写loadClass方法,即这里先尝试交由System类加载器加载,加载失败才会由自己加载。它并没有优先交给父类加载器,这就打破了双亲委派机制。 |
|