Equinox在创建Bundle的ClassLoader时,首先获取bundle的classpath,然后执行createBCLPrevileged方法,此方法最后转交由BaseData来创建ClassLoader。
BaseDate创建ClassLoader的关键代码片段为:
在Equinox中,默认的情况下adaptor.getBundleClassLoaderParent返回的为bootstrap classloader,可通过修改启动的osgi.parentClassLoader 来改变这个parent classloader,
osgi.parentClassLoader 的可选值有四个,分别是:
● boot:默认
● app:SystemClassLoader
● ext:SystemClassLoader的parent
● fwk:启动Equinox的ClassLoader
ClassLoadingHook在createClassLoader的时候都没有做动作,因此最后ClassLoader都是通过创建DefaultClassLoader对象来构建的,其中parent参数为null,delegate参数为BundleLoader实例,bundleclasspath参数为bundle的classpath。
经过以上步骤后,完成了ClassLoader的创建,可以开始加载class了,根据上面上述,Bundle的Class就由DefaultClassLoader来完成了。
查看DefaultClassLoader的loadClass代码,发现真正的加载class的过程是转为调用了delegate 的findClass来完成的,delegate参数对应的为BundleLoader实例,转为跟踪BundleLoader的findClass方法。
BundleLoader的findClass方法的代码片段:
从以上这个代码片段,可以看到,Equinox将java.开头的类转交给了parent classloader去加载,这也意味着没必要在系统中提供对外export java.开头的package。
如果不是java.开头的类,则交由findClassInternal方法来完成加载。
findClassInternal方法遵循的为OSGi规范中定义的Class的加载顺序,不过仍然稍有改动:
1)判断是否交由parent classloader去完成加载
在启动Equinox时,Equinox会读取org.osgi.framework.bootdelegation属性,该属性对应配置的为需要从parent classloader中加载的package,如值配置的为*,说明所有的都从parent classloader中加载 ,如值配置的为具体的package,那么则放入bootDelegation集合;如配置的为带通配符的package,那么则放入bootDelegationStems集合。
判断时Equinox首先判断是否所有的都从parent classloader中加载,如是则从parent classloader中加载;
如需要加载的类的package位于bootDelegation或bootDelegationStems集合中,那么同样从parent classloader中加载。
如不从parent classloader中加载,则进入下面的步骤。