双亲委托
双亲委托机制,就是导入类的时候判断parent是否已经导入过该类。
作用
1、避免重复加载,当父加载器已经加载了该类的时候,没有必要子ClassLoader再加载一次。
2、安全性考虑,防止核心API库被随意篡改。
核心代码
private final ClassLoader parent;
类是如何被加载的
调用loadclass加载
如果使用补丁包中的类
将补丁包插入到dexElement中,并且插入到dexElement列表的最前面。
已经加载过的类还能被替换修复吗
已经加载的类在缓存中了,不会再被加载了。所以Tinker Qzone需要重启生效,防止没有Bug类已经加载了,没法修复了。
如何保证正确的dex文件先被加载
将正确的dex放在dexlist数据
热修复流程
1、获取当前应用的PathClassloader;
2、反射获取到DexPathList属性对象pathList;
3、反射修改pathList的dexElements
a)将补丁包patch.dex转化为Element[](patch)
b)获得pathList的dexElements属性(old)
c)patch+old合并,并反射赋值给pathList的dexElements
反射基础
类加载
Class.forName()
加载 -> 链接 -> 初始化
Class.forName(A)会执行A中的静态代码块。
classLoader.loadClass()
classLoader.loadClass(A)不会执行A中的静态代码块。
判断程序的classLoader
public class MainActivity extends Activity {
private static final String TAG = "JJWorld.MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ClassLoader cls4 = Activity.class.getClassLoader();
Log.i(TAG, "" + cls4.getClass().getName());
ClassLoader cls1 = Dog.class.getClassLoader();
Log.i(TAG, "" + cls1.getClass().getName());
ClassLoader cls2 = AppCompatActivity.class.getClassLoader();
Log.i(TAG, "" + cls2.getClass().getName());
ClassLoader cls3 = MainActivity.class.getClassLoader();
Log.i(TAG, "" + cls3.getClass().getName());
} catch (Exception e) {
Log.i(TAG, "ClassLoader not found");
}
try {
Class<?> aClass = Class.forName("android.support.v4.app.SupportActivity");
Log.i(TAG, "aClass not found");
} catch (ClassNotFoundException e) {
Log.i(TAG, "class not found");
e.printStackTrace();
}
}
}
输出
2023-06-19 20:26:21.520 3061-3061/cn.jj.myapplication I/JJWorld.MainActivity: class not foundjava.lang.BootClassLoader
2023-06-19 20:26:21.520 3061-3061/cn.jj.myapplication I/JJWorld.MainActivity: dalvik.system.PathClassLoader
2023-06-19 20:26:21.520 3061-3061/cn.jj.myapplication I/JJWorld.MainActivity: dalvik.system.PathClassLoader
2023-06-19 20:26:21.520 3061-3061/cn.jj.myapplication I/JJWorld.MainActivity: dalvik.system.PathClassLoader
2023-06-19 20:26:21.520 3061-3061/cn.jj.myapplication I/JJWorld.MainActivity: class not found