在java中默认有三个加载器启动类加载器,扩展类加载器,应用类加载器启动类加载器是用来加载 Java 的核心类,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)查看启动类加载器的加载路径:
打印结果:
扩展类加载器负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。加载路径为java.ext.dirs查看扩展类加载器加载路径:
打印结果:
扩展类加载器初始化加载路径(将加载路径报错在ucp属性里,后面findClass方法会用到)
getExtClassLoader()->
createExtClassLoader()->
getExtDirs()->
应用类加载器加载Java 项目CLASSPATH下面的 Java 类或者JAR包
应用类加载器初始化加载路径(将加载路径报错在ucp属性里,后面findClass方法会用到)
类加载过程:classLoader.loadClass()
上图就是双亲委派机制的基本流程
当jvm加载一个类的时候,先让上层类加载器去加载,当上层类加载器加载不了,再由自己去加载。
Ext和App这两个加载器都继承了URLClassLoader,所以执行findClass方法的时候,其实值执行URLClassLoader.findClass方法。
URLClassLoader.findClass()
执行到findClass方法,会去判断该类是否在初始化的加载路劲里,如果在,执行defineClass(debug下去是native方法)方法去加载,不在,返回空