classLoader 顾名思义是用来 load class的,也就是加载class文件。java最终编译之后是class文件,要想运行必须把这些个文件加载到内存才行,classLoader就是干这个的,至于加载之后的链接(验证准备解析)和初始化不是本文的重点。
所谓的加载就是把class文件转换成byte[]加载到内存,随着学习的深入这个二进制数组会越来越频繁的出现,比如之前搞的加密操作的基础也是二进制数组。
jdk自带的classloader有三个 BootClassLoader,PlatformClassLoader(jdk9之前ExtClassLoader),AppClassLoader
其中BootClassLoader,PlatformClassLoader这两个加载是java自带的类,比如String int 这些java自带的类。
AppClassLoader加载是启动java项目时指定的classpath中的所有的类和文件,注意这里的描述是java -classpath xxx:xxx,是这个classpath后面所有的类。如果不加默认就是当前jar以及jar里面的lib文件夹下的jar包。
好吧,刚刚想着重现之前的问题,但是重现不了,现在是怎么导出怎么成功。我草你大爷的,这不科学吧?这个不重要了。
这三个加载器是有父子关系的,注意不是java里面的继承,而是聚合,但是聚合的属性就叫parent,AppClassLoader的parent是PlatformClassLoader,PlatformClassLoader的parent是BootClassLoader,
所以大家都叫父加载器。这里有个面试题,就是什么是双亲委派模型,英语是Parent Delegation Model。
这个听起来很高大上的名字很简单,就是如果对一个加载器发起一个加载文件的请求它不会直接加载,而是委托它的parent属性对应的加载器去加载,直到BootClassLoader这个最顶层的加载器,如果父加载器找不到再依次回来。
所以这个搜索文件的顺序也就有了,首先是存放java自带jar的文件夹,然后是classpath文件路径下的文件。直到今天才发现人还是得有自信,所有高大上的东西,都有他的逻辑性,而这些都可以被人理解。
到这里就可以自定义一个加载器了,自定义之后肯定是加载classpath之外的文件了,否则也没必要自己定义,直接使AppClassLoader就可以吧?这可以解决jar冲突的问题。