Android中的ClassLoader是主要有
BootClassLoader:负责加载Android FrameWork层中的字节码文件;
PathClassLoader:负责加载已经安装到系统APK文件中的字节码文件;
DexClassLoader:负责加载指定目录中的字节码文件;
通俗点的话:
DexClassLoader用于加载非APK部分的dex。(比如热补丁生成的dex)
PathClassLoader用于apk中开发者开发的类或者依赖库。(比如开发自己写的xxxActivity和support包里的AppCompatActivity)
BootClassLoader用于加载系统的类。(比如系统的Activity)
继承关系:
DexClassLoader 和 PathClassLoader 是 BaseDexClassLoader的子类
BaseDexClassLoader 和 BootClassLoader是ClassLoader的子类
(BootClassLoader就在ClassLoader.java文件里)
parent和child关系
DexClassLoader 的 parent我们通常会设置为 PathClassLoader 。
PathClassLoader的 parent是 BootClassLoader
双亲委托
先看下ClassLoader的loadClass方法
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先检查类是否已经被加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//parent不为空,则用parent的loadClass
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// 如果依旧没发现,则通过findClass去查找
c = findClass(name);
}
}
return c;
}
再看下DexClassLoader的findClass方法
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
ClassNotFoundException cnfe = new ClassNotFoundException(
"Didn't find class \"" + name + "\" on path: " + pathList);
for (Throwable t : suppressedExceptions) {
cnfe.addSuppressed(t);
}
throw cnfe;
}
return c;
}
去加载一个类的时候,首先查看该类是否被加载过,如果被加载过,则直接返回,如果没有则调用其父亲的加载类方法,同样查看其父亲是是否加载过,一直到顶层父亲都没有被加载过,则使用最顶层的父亲的findClass去加载,如果加载成功,则加入缓存中,如果不成功,则开始往回走,一直到最开始的加载类,调用其findClass方法去加载。
- 可以从缓存中获取,提高效率
- 加载一个类,需要先用最顶层的父类其加载,提高安全性。
网友评论