equinox环境下每一个bundle都是由独立的classLoader实现类的装载的。在OSGi Framework中,Bundle是模块化管理的单元,所有的应用和资源都必须以Bundle作为载体。每个Bundle都有自己的Class Loader,不同Bundle之间(在同一个VM中)可以通过Import和Export机制共享或者隐藏Package。Class Loader建立一种Loading Class的代理模型,来实现资源的共享或隐藏。
下面是equinox实现的类的装载代码:
ClassfindClass(Stringname,
boolean
checkParent)
throws
ClassNotFoundException{
StringpkgName = getPackageName(name);
// followtheOSGidelegationmodel
if (checkParent && parent != null ){
if (name.startsWith(JAVA_PACKAGE))
// 1)ifstartsWith"java."delegatetoparentandterminatesearch
// wewanttothrowClassNotFoundExceptionsifajava.*classcannotbeloadedfromtheparent.
return parent.loadClass(name);
else if (isBootDelegationPackage(pkgName))
// 2)ifpartofthebootdelegationlistthendelegatetoparentandcontinueoffailure
try {
return parent.loadClass(name);
} catch (ClassNotFoundExceptioncnfe){
// wewanttocontinue
}
}
Classresult = null ;
// 3)searchtheimportedpackages
PackageSourcesource = findImportedSource(pkgName);
if (source != null ){
// 3)foundimportsourceterminatesearchatthesource
result = source.loadClass(name);
if (result != null )
return result;
throw new ClassNotFoundException(name);
}
// 4)searchtherequiredbundles
source = findRequiredSource(pkgName);
if (source != null )
// 4)attempttoloadfromsourcebutcontinueonfailure
result = source.loadClass(name);
// 5)searchthelocalbundle
if (result == null )
result = findLocalClass(name);
if (result != null )
return result;
// 6)attempttofindadynamicimportsource;onlydothisifarequiredsourcewasnotfound
if (source == null ){
source = findDynamicSource(pkgName);
if (source != null )
result = source.loadClass(name);
}
// dobuddypolicyloading
if (result == null && policy != null )
result = policy.doBuddyClassLoading(name);
// lastresort;doclasscontexttricktoworkaroundVMbugs
if (result == null && findParentResource(name))
result = parent.loadClass(name);
if (result == null )
throw new ClassNotFoundException(name);
return result;
}
StringpkgName = getPackageName(name);
// followtheOSGidelegationmodel
if (checkParent && parent != null ){
if (name.startsWith(JAVA_PACKAGE))
// 1)ifstartsWith"java."delegatetoparentandterminatesearch
// wewanttothrowClassNotFoundExceptionsifajava.*classcannotbeloadedfromtheparent.
return parent.loadClass(name);
else if (isBootDelegationPackage(pkgName))
// 2)ifpartofthebootdelegationlistthendelegatetoparentandcontinueoffailure
try {
return parent.loadClass(name);
} catch (ClassNotFoundExceptioncnfe){
// wewanttocontinue
}
}
Classresult = null ;
// 3)searchtheimportedpackages
PackageSourcesource = findImportedSource(pkgName);
if (source != null ){
// 3)foundimportsourceterminatesearchatthesource
result = source.loadClass(name);
if (result != null )
return result;
throw new ClassNotFoundException(name);
}
// 4)searchtherequiredbundles
source = findRequiredSource(pkgName);
if (source != null )
// 4)attempttoloadfromsourcebutcontinueonfailure
result = source.loadClass(name);
// 5)searchthelocalbundle
if (result == null )
result = findLocalClass(name);
if (result != null )
return result;
// 6)attempttofindadynamicimportsource;onlydothisifarequiredsourcewasnotfound
if (source == null ){
source = findDynamicSource(pkgName);
if (source != null )
result = source.loadClass(name);
}
// dobuddypolicyloading
if (result == null && policy != null )
result = policy.doBuddyClassLoading(name);
// lastresort;doclasscontexttricktoworkaroundVMbugs
if (result == null && findParentResource(name))
result = parent.loadClass(name);
if (result == null )
throw new ClassNotFoundException(name);
return result;
}
从上面的代码可以看出什么呢?
1、解释了为什么在equinox的bundle中不需要引入java.*的包,而需要引入javax.*的包。
参见 equinox实现Class Loader机制的代码解读(2)
2、解释了如果import一个包名和当前bundle中的包名相同会发生什么。
参见equinox实现Class Loader机制的代码解读(3)
3、解释了如果使用了动态引入后,再次import相同的包产生的影响。
请参见后面的系列文章。