本文主要是基于android_10.0.0来讲述类加载的过程,涉及的代码类有
libcore/ojluni/src/main/java/java/lang/ClassLoader.java
libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
libcore/dalvik/src/main/java/dalvik/system/DexPathList.Element.java
libcore/dalvik/src/main/java/dalvik/system/DexFile.java
1:概述
我们首先从activity的实例化开始讨论,我们知道Activity的实例化在ActivityThread.java::performLaunchActivity中完成的
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
}
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
我们可以看到最终是通过classLoader的loadClass根据类名去加载的
2:类的查找过程
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);//loadedClass表示的是已经加载过得
if (c == null) {//如果没有加载过才去加载
try {
if (parent != null) {//调用父类的classLoader去加载
c = parent.loadClass(name, false);
} else {//如果父类的classLoader为空用Boot ClassLoader去加载
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);//用自己的
}
}
return c;
}
3:BaseDexClassLoader.java::findClass
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
我们知道BaseDexClassLoader是ClassLoader的直接子类
protected Class<?> findClass(String name) throws ClassNotFoundException {
// First, check whether the class is present in our shared libraries.
if (sharedLibraryLoaders != null) {//共享库对应的ClassLoader
for (ClassLoader loader : sharedLibraryLoaders) {
try {
return loader.loadClass(name);
} catch (ClassNotFoundException ignored) {
}
}
}
// Check whether the class in question is present in the dexPath that
// this classloader operates on.
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);//调用DexPathList的findClass方法
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;
}
4:DexPathList.java::findClass
public Class<?> findClass(String name, List<Throwable> suppressed) {
for (Element element : dexElements) {//遍历Element数组去查找
Class<?> clazz = element.findClass(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
if (dexElementsSuppressedExceptions != null) {
suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
}
return null;
}
5:DexPathList.Element.java::findClass
public Class<?> findClass(String name, ClassLoader definingContext,
List<Throwable> suppressed) {
return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed)
: null;
}
6:DexFile.java::loadClassBinaryName
private static Class defineClass(String name, ClassLoader loader, Object cookie,
DexFile dexFile, List<Throwable> suppressed) {
Class result = null;
try {
//通过本地方法defineClassNative来查找
result = defineClassNative(name, loader, cookie, dexFile);
} catch (NoClassDefFoundError e) {
if (suppressed != null) {
suppressed.add(e);
}
} catch (ClassNotFoundException e) {
if (suppressed != null) {
suppressed.add(e);
}
}
return result;
}
7:小结
7.1:双亲委派机制
类的查找是遵照双亲委派机制的,首先是判断是否已经加载过该类,如果没有则交给父类加载去加载,如果父类没有加载过就交给Boot ClassLoader(核心引导加载器)加载,如果还没有找到,则通过自身的classLoader去加载
7.2:java和android的类加载的差异
java加载的是.class,android加载的是dex,Android中没有了ExtClassLoader和AppClassLoader,取代他们的是PathClassLoader和DexClassLoader。
网友评论