从一个场景谈起: 代码里面用到Thread临时改变ContextClassLoader, 加载类之后,再设置回来的例子。所以研究一下ClassLoader.
基础:
三个ClassLoader: Bootstrap, Ext,App.
bootstrap用来加载java核心类,都放jre/lib里面;Ext用来加载扩展类,在ext文件夹里面;App用来加载classpath下面的类。这正好可以和配置java环境的时候的路径配置对应。
key1: 三者没有物理上的父子关系,只是逻辑上的。也就是parent只是classLoader的一个字段, 是设置的。而bootstrap都不是ext逻辑上的parent,只是功能上的。app和ext设置parent构造函数里面,而调用(传入parent)在Launcher里面。
key2: 类关系
app,ext ----->UrlClassLoader------->secureClassLoader---->classLoader, 各个环节的作用根据名字可以猜出来,具体就要看代码了。而app和ext都是Laucher的内部类。作为启动最主要的内容。
key3: Bootstrap是c++写的,jvm的一部分,所以在jdk里面没有。
有趣的点:
key1: Thread里面有个字段ContextClassLoader, 用来设置线程中的classLoader. 这里就有一个疑问了: 有啥用? 当前可以用上面那个场景回答,当前线程加载一下自己定义的类。
使用:
key1: classLoader里面已经写了, 自定义classLoader不要覆写loadClass, 覆写findClass; 不过并没有强制,也就是loadClass上面并没有什么final。 这样保证自定义classLoader依旧遵循双亲委派(为啥叫双亲呢, 估计是parent翻译,并不是真的有两个)。可以看一下loadClass的源码,很容易理解,先是缓存查找,找不到就父亲,没有父亲就bootstrap,最后findClass. findClass定义的就是查找类的方法。
key2: deineClass将二进制文件转成java 类。
遗留的点:
spring的类加载器。 貌似是自定义的。
网友评论