Android代码热修复基础-类只加载一次
来源:互联网 发布:tcp 51 udp 端口 编辑:程序博客网 时间:2024/06/06 17:39
Dalvik/Art虚拟机在加载类时只会加载第一个, 后续不再加载同名类。 基于这个特性,现在的热修复框架都是先加载patch.dex, 然后才是原来的classes.dex、classes2.dex。。。(PS:阿里Sophix是将patch取名为classes.dex, 把原来apk包的classes.dex改为classes2.dex, classes2.dex改为classes3.dex....... 腾讯Tinker是合并到classes.dex) 总之, 必须要先加载补丁dex才行。
常识: android虚拟机最先加载classes.dex文件, 所以要不像阿里Sophix那样改名,要么像Tinker那样合并patch到classes.dex.
如上图所示, 一个app至少有2个ClassLoader。
下面解释为什么.class只能加载一次,而且是第一次加载那个。
代码在ClassLoader.java:
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); //在native层查找是否已加载 if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { 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. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }函数体有synchronized关键字,说明它是线程安全的。 重点是findLoadedClass函数会根据完整类名去查找, 如果找不到再父容器查找parent.loadClass, 我们称之为双亲委托。
下面看一下ClassLoader是怎么查找类的:
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, jstring javaName) { ScopedFastNativeObjectAccess soa(env); mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader); ScopedUtfChars name(env, javaName); ... std::string descriptor(DotToDescriptor(name.c_str())); const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str());//类名javaName转换成hashcode mirror::Class* c = cl->LookupClass(soa.Self(), descriptor.c_str(), descriptor_hash, loader);//查找 if (c != nullptr && c->IsResolved()) {
代码最终走到这里。
Android开发可能用到的还有PathClassLoader和DexClassLoader, 一般热修复用DexClassLoader,因为不须安装。
阅读全文
0 0
- Android代码热修复基础-类只加载一次
- Android热修复技术(三)-----代码修复之冷启动类加载原理
- 类加载机制实现Android热修复
- Android 使用类加载器原理实现热修复
- Android之切换Fragment只加载一次
- Android 热修复/热更新
- Android热修复(动态加载)方案汇总
- Android RocooFix热修复动态加载框架介绍
- Android热修复三部曲之动态加载补丁.dex文件
- Android热修复三部曲之动态加载补丁.dex文件
- Android 热修复方案Tinker(三) Dex补丁加载
- Android 热修复方案Tinker(二) 补丁加载流程
- Android 热修复方案Tinker(三) Dex补丁加载
- Android动态加载之热修复与插件化
- Android 热修复方案Tinker(四) 资源补丁加载
- Android 热修复方案Tinker(五) SO补丁加载
- android热修复--手写热修复
- Android viewpager + fragment 的懒加载 只加载一次
- 【Spring】Spring MVC原理及配置详解
- java中数值转换的总结
- Android性能调优利器StrictMode
- 这些自动贩卖机太棒了,在车站专卖短篇小说
- BZOJ 3135: [Baltic2013]pipes
- Android代码热修复基础-类只加载一次
- linux下的多线程编程
- 自己写的Linux基础笔记
- DES,RSA加解密,base64格式字符串转换,字典排序
- 面试题----SQL
- 剑指Offer_面试题07_用两个栈实现队列
- Node 的单元测试--jasmine
- Linux下使用C/C++访问数据库——SQL Server篇
- spark