1.什么是类加载器?
虚拟机设计团体把类加载阶段中的"通过一个类的全限定名来获取描述此类文件的二进制字节流",这个动作方法Java虚拟机外部去实现,以便让应用才程序自已决定如何获取所需要的类。实现这个 动作的代码模块称为“类加载器”。
2.类加载器:
启动类加载器(BootStarap ClassLoader):启动类是由C++实现的,负责将存放在<JAVA_HOME>\lib目录中,或者被-Xbootclasspath参数所指定的路径中,并且是虚拟机识别的(仅按照文件名识别,如rt.jar名字不符合的类库即使放在lib目录中也不会加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器的时,需要把加载请求委派给启动类加载器,那直接使用null代替即可。
扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指的的路径中的所有类库。
应用程序类加载器(Application ClassLoader): 负责加载用户类路径(classpath
)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
3.双亲委派模型(Parents Delegation Model):
双亲委派模型除了要求顶层的启动类加载器外,其他的类加载器都应当有自已的父类加载器。这里的类加载器之间的父子关系一般不会以继承(Inheritance) 的关系来实现,而是使用组合(Composition)关系来复用父加载器的代码。
4.双亲委派模型的工作流程:
如果一个类加载器收到了类加载请求,它首先不会自已去尝试加载这个类,而是会把这个请求委派给父类的加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自已无法完成这个加载请求(他的搜索范围中没有找到所需的类)时,子加载器才会尝试自已去加载。
5.为什么要使用双亲委派模型:
黑客自定义一个java.lang.String
类,该String
类具有系统的String
类一样的功能,只是在某个函数稍作修改。比如equals
函数,这个函数经常使用,如果在这这个函数中,黑客加入一些“病毒代码”。并且通过自定义类加载器加入到JVM
中。此时,如果没有双亲委派模型,那么JVM
就可能误以为黑客自定义的java.lang.String
类是系统的String
类,导致“病毒代码”被执行。