Jar冲突解决一
目的是classpath中线性的jar排列扩展成树型排列。
方案原理
遍历classpath,对于每个jar定制一个ComponentClassLoader,每个jar内部的mainfest文件存储这个jar的依赖关系,由ManagerClassLoader负责根据依赖关系找到相应的ComponentClassLoader加载。如下是静态依赖关系:
ComponentClassLoader
继承自URLClassLoader,用于加载每个classpath中的jar,其parent Classloader是ManagerClassLoader.
ManagerClassLoader
继承于ClassLoader,当ComponentClassLoader在其对应的jar内无法加载时,委托给ManagerClassLoader,ManagerClassLoader会从其依赖列表里面去加载。
WarpperClassLoader
用于取代java默认的SystemClassLoader.
加载流程
启动注册
Classpath中的每个Jar对应一个ComponentClassLoader, 同时读取jar中的MAINFEST文件配置,加载Jar之间的依赖关系,并在ComponentClassLoader保存这个依赖列表。
加载规则
对于一个Class:
WarpperClassLoader自己加载,循环调用所有注册的ComponentClassLoader来加载.
ComponentClassLoader在自己所在的Jar中加载类,如果加载到就返回;如果没有加载到,则统一调用ManagerClassLoader从依赖列表类中加载。
如果ComponentClassLoader无法加载到则依次委托给extension,bootstrap加载。
备注
:Jar之间的依赖关系保存在Jar内部的META-INF/MAINFEST中,这个非常重要,依赖关系列表弄错就无法正确加载。
配置部署
将上面3个class打包成loader.jar,在启动参数中添加如下命令
-Xbootclasspath/a:lib/loader.jar -Djava.system.class.loader=com.conflict.WrapperClassLoader