package zeus.plugin;
import android.text.TextUtils;
import static java.lang.System.arraycopy;
/***
* 这是一个空ClassLoader,主要是个容器
* <p>
* Created by huangjian on 2016/6/21.
*/
class ZeusClassLoader extends ClassLoader {
//这里每个插件对应着一个ClassLoader,一旦插件更新了,则classLoader也会使用新的。
//这样java的class就会从新的classLoader中查找,而不会去使用旧的classLoader的缓存
private ZeusPluginClassLoader[] mClassLoader = null;
public ZeusClassLoader(ClassLoader parent) {
super(parent);
}
public ZeusPluginClassLoader[] getClassLoaders() {
return mClassLoader;
}
/**
* 添加一个插件到当前的classLoader中
*
* @param pluginId 插件名称
* @param dexPath dex文件路径
* @param libPath so文件夹路径
*/
protected void addAPKPath(String pluginId, String dexPath, String libPath) {
if (mClassLoader == null) {
mClassLoader = new ZeusPluginClassLoader[1];
} else {
int oldLenght = mClassLoader.length;
Object[] old = mClassLoader;
mClassLoader = new ZeusPluginClassLoader[oldLenght + 1];
arraycopy(old, 0, mClassLoader, 0, oldLenght);
}
mClassLoader[mClassLoader.length - 1] = new ZeusPluginClassLoader(pluginId, dexPath,
PluginUtil.getDexCacheParentDirectPath(),
libPath,
getParent());
}
/**
* 移除一个插件classLoader
*
* @param pluginId 插件id
*/
protected void removePlugin(String pluginId) {
if (mClassLoader == null || TextUtils.isEmpty(pluginId)) return;
for (int i = 0; i < mClassLoader.length; i++) {
ZeusPluginClassLoader cl = mClassLoader[i];
if (pluginId.equals(cl.getPluginId())) {
if (mClassLoader.length == 1) {
mClassLoader = null;
return;
}
int oldLength = mClassLoader.length;
Object[] old = mClassLoader;
mClassLoader = new ZeusPluginClassLoader[oldLength - 1];
if (i != 0) {
arraycopy(old, 0, mClassLoader, 0, i);
}
if (i != oldLength - 1) {
arraycopy(old, i + 1, mClassLoader, i, oldLength - i - 1);
}
return;
}
}
}
@Override
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = null;
try {
//先查找parent classLoader,这里实际就是系统帮我们创建的classLoader,目标对应为宿主apk
clazz = getParent().loadClass(className);
} catch (ClassNotFoundException ignored) {
}
if (clazz != null) {
return clazz;
}
//挨个的到插件里进行查找
if (mClassLoader != null) {
for (ZeusPluginClassLoader classLoader : mClassLoader) {
if (classLoader == null) continue;
try {
//这里只查找插件它自己的apk,不需要查parent,避免多次无用查询,提高性能
clazz = classLoader.loadClassByself(className);
if (clazz != null) {
return clazz;
}
} catch (ClassNotFoundException ignored) {
}
}
}
throw new ClassNotFoundException(className + " in loader " + this);
}
}