在JVM加载Class时,会通过不同的类加载器来进行加载,直接上图:
每个类加载器都有负责需要加载的区域
1-启动类加载器,负责加载%JAVA_HOME%\bin目录下的所有jar包,或者是-Xbootclasspath参数指定的路径。
2-扩展类加载器:负责加载%JAVA_HOME%\bin\ext目录下的所有jar包,或者是java.ext.dirs参数指定的路径。
3-应用程序类加载器:负责加载用户类路径上所指定的类库,如果应用程序中没有自定义加载器,那么次加载器就为默认加载器。
可以通过程序进行验证每个加载器都加载哪些内容:
在类加载的过程中,首先从AppClassLoader进行加载(此处不考虑自定义类加载器),如果没有获取到class,会委托类加载器的父节点(ClassLoader.parent)进行再次查询(递归),如果流转到顶级节点(BootStrapClassLoader)依旧没有获取到Class,会在顶级节点进行尝试加载,如果当前类加载器无法加载,会将Class流转到下一节点ExtClassLoader进行加载,如果依旧无法加载,则继续流转到AppClassLoader,如果也无法进行加载,则抛出ClassNotFoundException
参考代码:java.lang.ClassLoader#loadClass(java.lang.String, boolean)
源码:
findClass 为模板方法,各类加载器实现机制不同,但是ExtClassClassLoader 和 AppClassLoader都继承了URLClassLoader,类加载在此实现,源码:
java.net.URLClassLoader#findClass
此处注意:各类加载器并非继承关系,只是靠ClassLoader.parent 属性进行关联 ,在使用类加载器的过程中,如果发现了Class,会直接进行返回,而不是替换
总结:向上查找,向下加载,故为双亲委派