atlas [use][bug]: BundleClassLoader 的 startBundle 方法中没有对 STARTING 状态进行处理

xuo3flqw  于 5个月前  发布在  其他
关注(0)|答案(4)|浏览(74)

BundleClassLoader 的 startBundle 方法中没有对 STARTING 的 state 进行处理, 在特殊场景下会导致该 Bundle 的自定义 Application 的 onCreate 方法会被重复调用,最后会导致方法栈溢出

`
public synchronized void startBundle() {
if (state == UNINSTALLED) {
throw new IllegalStateException("Cannot start uninstalled bundle " + toString());
}
if (state == ACTIVE) {
return;
}
if (state == INSTALLED) {
throw new RuntimeException("can not start bundle which is not resolved");
}
// 需要添加对 STARTING 状态的判断
if (state == STARTING) {
return;
}
state = STARTING;
Framework.notifyBundleListeners(BundleEvent.BEFORE_STARTED, this);
Framework.notifyBundleListeners(BundleEvent.STARTED, this);
if (Framework.DEBUG_BUNDLES) {
Log.i("Framework","Bundle " + toString() + " started.");
}
}

`

cwxwcias

cwxwcias1#

能详细描述下特殊场景么? 我们对bundle的start 是做了同步的。

s3fp2yjn

s3fp2yjn2#

@hwjump
我的项目中有一个 FirstBundle 依赖 LibBundle,LibBundle的Application的onCreate方法中调用了Host的一个方法通过 DelegateClassLoader 加载LibBundle中的一个类;
运行时是 Host 先安装 FirstBundle,FirstBundle 中加载了 LibBundle 中的一个类,这时就会触发LibBundle的安装, 当 Atlas 框架调用 LibBundle 的Application的onCreate方法时,onCreate方法会调用Host的一个方法来加载一个LibBundle中的类,这时DelegateClassLoader会走到loadFromInstalledBundles方法通过遍历每个Bundle来查找类,查找到 FirstBundle 时,因为FirstBundle有一个 LibBundle 的依赖,所以又会去通过下面的代码查找 LibBundle 中的类

BundleClassLoader类的findClass方法代码片段:
// find class in dependency bundle
if (dependencies != null) {
for (String dependencyBundle : dependencies) {
try {
BundleImpl impl = (BundleImpl) Atlas.getInstance().getBundle(dependencyBundle);
if(impl!=null) {
impl.startBundle();
clazz = ((BundleClassLoader) impl.getClassLoader()).loadOwnClass(classname);
if (clazz != null) {
return clazz;
}
}else{
Log.e("BundleClassLoader",String.format("%s is not success installed by %s",""+dependencyBundle,location));
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}

虽然你说Atlas框架中通过了synchronized的方式同步startBundle方法,但是debug查看方法栈时的确会发现同一个 BundleImpl对象的startBundle方法会嵌套调用,并且所有调用都在主线程中;
AtlasCore的版本为5.0.7.55,AtlasPlugin的版本为2.3.3.rc37

umuewwlo

umuewwlo3#

我们其实是不建议使用 DelegateClassLoader 加载LibBundle中的一个类,1来慢,2来隔离性太差。 所以我建议你改一下代码结构,做个更好的隔离出来。 另外后续我们会加强DelegateClassLoader的访问。劲量不让外部直接访问到。

rsl1atfo

rsl1atfo4#

@hwjump 那只能先用Host的PathClassLoader来查找,查找不到再根据类的包名去找相应的BundleClassLoader去加载类,淘宝的 ServerHub 框架是怎样加载不同bundle中的类的?

相关问题