1.1什么是类加载器?
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。
一个类在同一个类加载器中具有唯一性(Uniqueness),而不同类加载器中是允许同名类存在 的,这里的同名是指全限定名相同。但是在整个JVM里,纵然全限定名相同,若类加载器不 同,则仍然不算作是同一个类,无法通过 instanceOf 、equals 等方式的校验
1.2系统提供的三个类加载器
- 启动类加载器(Bootstrap Class Loader): 负责将存放在<JAVA_HOME>\lib目录中,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。(注:仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)
- 扩展类加载器(Extension Class Loader): 负责加载<JAVA_HOME>\lib\ext目录中的,或被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
- 应用程序类加载器(Application Class Loader): 负责加载用户路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,一般情况下该类加载是程序中默认的类加载器。
1.3双亲委派模型
如上图展示的类加载器之间的这种层次关系就是双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其他的类加载器都应有自己的父类加载器。
如果一个类加载器收到类加载的请求,他首先不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,每一层次的类加载器都是这样,因此所有的加载请求最终都应该传送到底层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试去加载。
1.4破环双亲委派模型
双亲委派这个模型并不是强制模型,而且会带来一些些的问题。就比如java.sql.Driver这个东西。 JDK只能提供一个规范接口,而不能提供实现。提供实现的是实际的数据库提供商。提供商的库总不能放JDK目录里吧。
-
如果我们自定义的加载器不想破坏双亲委派,继承 java.lang.ClassLoader 类并重写 findClass 方法。
-
如果使用我们自定义的加载器破坏双亲委派,继承 ava.lang.ClassLoader 类并重写loadClass(java.lang.String) 方法。