OSGi简介
OSGi: Open Services Gateway Initiative,它的初衷是建立一个开放性的平台,通过这个平台可以很容易的发布可管理的服务和应用到本地网络和设备,以达到设备管理的目的。JSR232和OSGi有着密切的联系(其实是完全一样的),JSR232就是OSGi的Framework规范加上OSGi Mobile的规范。OSGi Framework主要解决底层Runtime Model问题,而OSGi Mobile是基于OSGi Framework之上的关于OMA DM的实现。
OSGi目前的应用越来越广泛,特别是OSGi Framework。像Eclipse就是基于OSGi Framework之上扩展出来的。而且,当前很多企业级的架构,例如Spring等等都把自己的Runtime Model建立在OSGi Framework之上。接下来,我将就OSGi Framework最神秘最吸引人(自认为)的Class Loading架构进行阐述。
2. Class Loading Architecture
在OSGi Framework中,Bundle是模块化管理的单元,所有的应用和资源都必须以Bundle作为载体。每个Bundle都有自己的Class Loader,不同Bundle之间(在同一个VM中)可以通过Import和Export机制共享或者隐藏Package。Class Loader建立一种Loading Class的代理模型,来实现上面所说的共享或隐藏机制:
Class Loader可以从以下几个方面来加载Classes和Resources:
· Boot class path — 主要包括java.*和实现的Packages。
· Framework class path — Framework其实也是Bundle,只不过叫System Bundle,那么它也会有自己的class loader。
· Bundle Space — 当然就是Bundle自己啦以及一些附加的资源,例如Fragments。
如果给定一个Bundle Class Loader,那么这个Class Loader所能访问的classes包括(这就是所谓的Class Space):
· Parent class loader所加载的classes,通常是java.*之类的classes。
· Imported packages
· Required bundles
· Bundle 自身的Classpath
· Fragment
同一个Class Space不能存在这种情况:两个类拥有相同的Qualified Name(Name Space + Simple Class Name)。而不同的Class Space则可以存在这种情况,即两个类拥有相同的Qualified Name。这使得,在同一个VM中,可以同时存在一个类的不同版本。
3. Runtime Class Loading
当一个Bundle Class Loader加载一个class或resource时,它的步骤如下:
- 如果这个被加载的class或资源包含在Java.*包中,那么这个加载请求就会被传递给Parent Class Loader;否则,进入下一步。如果请求被传递给Parent Class Loader,而Parent Class Loader也没找到相应的资源,那么加载过程以失败结束。
- 如果包含被加载的class或resource的package被定义在Boot Delegation表中时(org.osgi.framework.bootdelegation),那么这个请求将被传递到Parent Class Loader。如果找到相应的class或resource,那么加载过程以成功结束。
- 如果这个被加载的class或resource包含在Import-Package中,那么这个请求将被传递到Export这个Package的Bundle Class Loader(此时,这个class或资源可能已经被加载到VM中了)。否则进入下一步。
- 如果这个被加载的class或resource包含在Required-Bundle中,那么这个请求将被传递给这个Required-Bundle Class Loader。如果没有找到,那么进入下一步。
- 在此Bundle自身的class path中寻找被加载的class或资源。如果没有找到,那么进入下一步。
- 在此Bundle的Fragment的class path中寻找,查询按Fragment的Bundle ID的顺序。如果没有找到,那么进入下一步。
- 如果这个被加载的class或resource包含在Import-Package或Required-Bundle中(但是到这一步还是没有找到),那么加载过程以失败结束。否则,进入下一步。
- 如果这个被加载的class或resource包含在DynamicImport-Package中,那么这个Dynamic Import将被建立。如果这个Dynamic Import不能成功建立(主要看依赖条件是否被满足),那么加载过程以失败结束。
- 如果Dynamic Import成功建立,那么这个请求将被传递给Export这个package的Bundle Class Loader。如果在这种情况下,也没有找到class或resource,那么加载过程以失败结束。
以下是具体的流程图(来源于OSGi core specification R4):
v