背景
Android开发过程中,开发的小伙伴对动态加载代码肯定不陌生,在使用各个开源框架的过程中都应该有接触。其主要原理离不开ClassLoader等相关的类。这里我们会从Android中ClassLoader等相关类的源码入手,更好的理解和学习动态加载类的原理。
详细分析ClassLoader加载原理
ClassLoader 的继承关系如下:
这里我们主要分析一下 BaseDexClassLoader.findClass()
和 ClassLoader.loadClass()
两个函数的在系统中是怎么进行查找class的过程。
我们看一下系统加载类ClassLoader.loadClass()
函数实现代码,在ClassLoader.java
中:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 首先 检测是否已经加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//去调用父类的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在当前dex查找
c = findClass(name);
}
}
return c;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
- 1,
loadClass()
先调用findLoadedClass()
来判断当前类是否已加载; - 2, 未查找到递归去父类中查找是否加载到缓存;
- 3, 均未缓存,去
BootClassLoader
中查找; - 4, 以上未发现,自顶级父类依次向下查找,调用
findClass()
查找当前dex。
findLoadedClass函数分析
下图为
findLoadedClass()
的调用流程;根据调用流程图配合源代码进行详细的分析原理。
下面介绍对应的源代码实现部分:
protected final Class<?> findLoadedClass(String name) {
ClassLoader loader;
if (this == BootClassLoader.getInstance())
loader = null;
else
loader = this;
return VMClassLoader.findLoadedClass(loader, name);
}
函数最终统一调用VMClassLoader.findLoadedClass()
进行查找类。
native static Class findLoadedClass(ClassLoader cl, String name);
实现在java_lang_VMClassLoader.cc
文件中。
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,jstring javaName) {
....
ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(javaLoader);
ClassLinker* cl = Runtime::Current()->GetClassLinker();
ObjPtr<mirror::Class> c = VMClassLoader::LookupClass(cl,
soa.Self(),