类加载器的结构图:
- 启动类加载器:由C++实现,负责加载JAVA_HOME\lib目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
- 扩展类加载器:负责加载JAVA_HOME\lib\ext目录中的,或通过java.ext.dirs系统变量指定路径中的类库。
- 应用程序类加载器:负责加载用户路径(classpath)上的类库。
- 自定义类加载器:通过继承java.lang.ClassLoader实现自定义的类加载器。
双亲委派模型:当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务都会传递到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会尝试执行加载任务。
双亲委派模型,所有的类加载器都会从其最终父类启动类加载器开始从上往下加载类,
那么位于rt.jar中的java.lang.String自然会被优先加载。
这也是双亲委派模型的好处:即避免了类的重复加载,也保证了 Java 的核心 API 不被篡改。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为java.lang.Object类的话,那么程序运行的时候,系统就会出现多个不同的Object类。