前言:
要想明白Atlas的类加载机制,就要了解OSGI 框架,因为查看Atlas源码会发现Atlas的核心思想就是OSGI。
OSGI
osgi 的主要特点是有灵活的类加载器框架,osgi的bundle类加载器之间只有规则没有固定的委派关系。接下来让我们来看看Atlas的具体类加载规则。
OSGi为每个bundle提供一个类加载器,该加载器能够看到bundle Jar文件内部的类和资源;
Atlas 源码中的实现:
BundleImpl 是OSGI 框架 Bundle的一个具体实现,它的类加载器是怎样实现的呢?
//Framework.java 中安装Bundle的时候创建的Bundle实例
BundleImpl bundle = null;
BundleListing.BundleInfo info = AtlasBundleInfoManager.instance().getBundleInfo(location);
bundle = new BundleImpl(bundleDir, location, in, null, info.getUnique_tag(),true,-1l);
创建实例对象的过程中分析改bundle的依赖关系,然后为改bundle创建一个ClassLoader
private synchronized void resolveBundle() throws BundleException {
if (this.archive == null) {
throw new BundleException("Not a valid bundle: " + location);
}
if (this.state == RESOLVED){
return;
}
if ( this.classloader == null){
// create the bundle classloader
List<String> dependencies = AtlasBundleInfoManager.instance().getDependencyForBundle(location);
String nativeLibDir = getArchive().getCurrentRevision().mappingInternalDirectory().getAbsolutePath()+"/lib"+":"
+ RuntimeVariables.androidApplication.getApplicationInfo().nativeLibraryDir+":"
+System.getProperty("java.library.path");
if(dependencies!=null) {
for (String str : dependencies) {
BundleImpl impl = (BundleImpl) Atlas.getInstance().getBundle(str);
if (impl != null) {
nativeLibDir += ":";
File dependencyLibDir = new File(impl.getArchive().getCurrentRevision().mappingInternalDirectory(), "lib");
nativeLibDir += dependencyLibDir;
}
}
}
this.classloader = new BundleClassLoader(this,dependencies,nativeLibDir);
}
state = RESOLVED;
// notify the listeners
Framework.notifyBundleListeners(0 /*LOADED*/, this);
}
到此为止Bundle的classLoader 创建完成。
为了让bundle能互相协作,可以基于依赖关系,从一个bundle类加载器委托到另一个bundle类加载器。
让我们看看Atlas的具体实现:
1. bundle 会先从自身查找该类(findOwnClass)。
2. 如果没有找到就遍历依赖的bundle
3. 获取依赖bundle的classLoader
4. 查找目标类
5. 如果没有找到抛出ClassNotFoundException
protected Class<?> findClass(final String classname) throws ClassNotFoundException {
Class<?> clazz;
// okay, check if it is in the scope of this classloader
clazz = findOwnClass(classname);
if (clazz != null) {
if (classLoadListener != null) {
classLoadListener.onClassLoaded(clazz);
}
return clazz;
}
// find class in PathClassLoader
try {
clazz = Framework.systemClassLoader.loadClass(classname);
if (clazz != null) {
return clazz;
}
} catch (Exception e) {
}
// find class in dependency bundle
if (dependencies != null) {
for (String dependencyBundle : dependencies) {
try {
BundleImpl impl = (BundleImpl)Atlas.getInstance().getBundle(dependencyBundle);
if (impl != null) {
clazz = ((BundleClassLoader)impl.getClassLoader()).loadOwnClass(classname);
if (clazz != null) {
impl.startBundle();
return clazz;
}
} else {
Log.e("BundleClassLoader",
String.format("%s is not success installed by %s", "" + dependencyBundle, location));
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
throw new ClassNotFoundException(
"Can't find class " + classname + " in BundleClassLoader: " + bundle.getLocation() + ", dependencies="
+ dependencies + ", thread=" + Thread.currentThread());
}
总结:
Java和J2EE 的类加载模型都是层次化的,只能委托给上一层的类记载器,而OSGI类加载模型则是网络状的,可以在bundle间互相委托。
例如bundleA、B都依赖于bundleC,当他们访问bundleC中的类时,就会委托给bundleC的类加载器,由它来查找类;如果它发现还要依赖bundleE中的类,就会再委托给bundleE的类加载器。