参考文章
类的生命周期
类的生命周期可以参看下图
其中,加载阶段可以细分如下
1. 加载类的二进制流
2. 数据结构转换,将二进制流所代表的静态存储结构转化方法区的运行时的数据结构
3. 生成java.lang.Class对象,作为方法区这个类的各种数据的访问入口
加载类的二进制流有以下方法
1. 从zip包中读取,这就发展成了我们常见的JAR、AAR依赖
2. 运行时动态生成,这就是我们常见的动态代理技术,在java.reflect.Proxy中就是用ProxyGenerateProxyClass来为特定的接口生成代理的二进制流
加下来就要详细说下Android的ClassLoader,不过讲之前,需要先介绍下双亲委托机制
双亲委托机制
其实很简单,一句话
先自己的缓存里面找有没有加载过这个类,如果没有,找parent加载,如果parent也没有,就自己加载。
要记住,这里的parent不是父类的意思,不是父类的意思,不是父类的意思。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
//先从缓存中加没加载这个类
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//从parent中加载
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) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
return c;
}
看一下findClass的实现,(BootClassLoader,大部分的ClassLoader的parent都是这个)
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return Class.classForName(name, false, null);
}
哈哈,就是我们熟悉的classForName
Android的ClassLoader
是时候祭出这张广为人知的图了。
先挨个介绍一下
- ClassLoader是一个抽象类,定义了ClassLoader的主要功能
- BootClassLoader是ClassLoader的子类(注意不是内部类,有些材料上说是内部类,是不对的),用于加载一些系统Framework层级需要的类,是Android平台上所有的ClassLoader的最终parent
- SecureClassLoader扩展了ClassLoader类,加入了权限方面的功能,加强了安全性
- URLClassLoader继承SecureClassLoader,用来通过URI路径从jar文件和文件夹中加载类和资源,在Android中基本无法使用
- BaseDexClassLoader是实现了Android ClassLoader的大部分功能
- PathClassLoader加载应用程序的类,会加载/data/app目录下的dex文件以及包含dex的apk文件或者java文件(有些材料上说他也会加载系统类,我没有找到,这里存疑)
- DexClassLoader可以加载自定义dex文件以及包含dex的apk文件或jar文件,支持从SD卡进行加载。我们使用插件化技术的时候会用到
- InMemoryDexClassLoader用于加载内存中的dex文件
看下代码
logcat("Object classLoader:" + Any::class.java.classLoader + ":" + Any::class.java.classLoader?.parent)
logcat("HomeActivity classLoader:" + HomeActivity::class.java.classLoader + ":" + HomeActivity::class.java.classLoader?.parent)
logcat("activity classLoader:" + Activity::class.java.classLoader + ":" + Activity::class.java.classLoader?.parent)
日志
2021-02-04 11:36:32.015 3220-3220/com.xxx E/lklog: Object classLoader:java.lang.BootClassLoader@c38876d:null
2021-02-04 11:36:32.015 3220-3220/com.xxx E/lklog: HomeActivity classLoader:dalvik.system.PathClassLoader[DexPathList[[zip file "/system/framework/android.test.mock.jar", zip file "/system/framework/android.test.runner.jar", zip file "/data/app/com.lukouapp-EotfkXsC9iBY-fX92CCqzg==/base.apk"],nativeLibraryDirectories=[/data/app/com.lukouapp-EotfkXsC9iBY-fX92CCqzg==/lib/arm, /data/app/com.lukouapp-EotfkXsC9iBY-fX92CCqzg==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]]:java.lang.BootClassLoader@c38876d
2021-02-04 11:36:32.015 3220-3220/com.xxx E/lklog: activity classLoader:java.lang.BootClassLoader@c38876d:null
从上面日志可以看到以下信息
1. Any和Activity这类系统类的classloader都是BootClassLoader
2. 自定义类的ClassLoader是PathClassLoader,但parent也是BootClassLoader,并且与上面的ClassLoader是同一个实例