EP2 加载后的类存在的期限
0x01 加载后的类存在的期限
昨天说到的问题是,ClassLoader在一个App中至少有两个实例,一个是系统启动时创建的Boot类型的,一个是App中fork出来的;而且如果一个类被加载过,那么这个类永远不会被重新加载。 这个「永远」的期限是什么呢?
我们可以看看ClassLoader的实现。ClassLoader是Abstract类型,我们要使用它的子类DexClassLoader、PathClassLoader 来实现类加载。 从网络上可以查到,DexClassLoader、PathClassLoader 的区别是:
- DexClassLoader 可以加载 jar/apk/dex,可以从 SD 卡中加载未安装的 apk;
- PathClassLoader 只能加载系统中已经安装过的 apk;
// DexClassLoader.java
public class DexClassLoader extends BaseDexClassLoader {public DexClassLoader(String dexPath, String optimizedDirectory,String libraryPath, ClassLoader parent) {super(dexPath, new File(optimizedDirectory), libraryPath, parent);}
}
复制代码
DexClassLoader的构造参数有dexPath,optimizedDirectory,libraryPath和parent。
// PathClassLoader.java
public class PathClassLoader extends BaseDexClassLoader {public PathClassLoader(String dexPath, ClassLoader parent) {super(dexPath, null, null, parent);}public PathClassLoader(String dexPath, String libraryPath,ClassLoader parent) {super(dexPath, null, libraryPath, parent);}
}
复制代码
PathClassLoader的构造参数就只有dexPath和libraryPath,少了一个optimizedDirectory(super中传了null)。那么,看来这个optimizedDirectory就是为什么PathClassLoader「只能加载系统中已经安装过的 apk」的原因。
看看他们共同的父类BaseDexClassLoader里面的实现:
public BaseDexClassLoader(String dexPath, File optimizedDirectory,String libraryPath, ClassLoader parent) {super(parent);this.originalPath = dexPath;this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);}
复制代码
创建了系统自动loadClass之后的dexPath,以及一个DexPathList对象。 在DexPathList.java中有这样的方法:
private static DexFile loadDexFile(File file, File optimizedDirectory)throws IOException {if (optimizedDirectory == null) {return new DexFile(file);} else {String optimizedPath = optimizedPathFor(file, optimizedDirectory);return DexFile.loadDex(file.getPath(), optimizedPath, 0);}
}
复制代码
以及:
/*** Converts a dex/jar file path and an output directory to an* output file path for an associated optimized dex file.* 为关联的最优化dexfile把dex/jar文件路径和输出目录转换成一个output文件路径*/
private static String optimizedPathFor(File path,File optimizedDirectory) {String fileName = path.getName();if (!fileName.endsWith(DEX_SUFFIX)) {int lastDot = fileName.lastIndexOf(".");if (lastDot < 0) {fileName += DEX_SUFFIX;} else {StringBuilder sb = new StringBuilder(lastDot + 4);sb.append(fileName, 0, lastDot);sb.append(DEX_SUFFIX);fileName = sb.toString();}}File result = new File(optimizedDirectory, fileName);return result.getPath();
}
复制代码
也就是optimizedDirectory用来存储加载的dex文件,比如想要加载sd卡上的dex,就填写对应的文件路径。
return DexFile.loadDex(file.getPath(), optimizedPath, 0);
复制代码
所以昨天的问题大概清楚了,既然是创建了一个文件来保存,而且这个文件是保存到应用内的(file.getPath()),所以类加载之后保存的「期限」就是在应用清空缓存或者卸载应用前。
前面我们了解到,凡是被父母加载过的类都不会重新被加载。这样的话,如果想要动态更新一个类,比如想要用到更新插件apk来实现「热修复」,就必须用一个不同的类,否则classloader会使用加载过的类。所以我们在使用新的插件的时候,要构造一个新的classLoader来加载这个插件的dex。或者,也许可以先清空之前加载过的dex的缓存路径。
时间不够了,明天再说吧。
-NOV22
转载于:https://juejin.im/post/5a313423f265da431c704e8a
EP2 加载后的类存在的期限相关推荐
- SpringMVC几个核心类(控制器核心类,加载配置文件核心类,处理url影射核心类,处理视图资源核心类,方法动态调用核心类)
核心类 制器核心类: •org.springframework.web.servlet.DispatcherServlet - 配置web.xml 加载配置文件核心类: •org.springf ...
- 页面加载后如何使JavaScript执行?
我正在使用<head>内的<script>执行外部脚本. 现在,由于脚本是在页面加载之前执行的,因此我无法访问<body> . 在文档"加载"后 ...
- springboot 启动分析【难点】——如何自动扫描 @SpringBootApplication||如何加载自动配置类 @EnableAutoConfiguration||如何加载前端控制器
springboot 启动分析[难点] 自动扫描的特点 默认扫描与 启动类 同级的所有包及其子包都可以自动扫描 如果不可要使用@ComponentScan(basePackage={"&qu ...
- 自定义标签报 无法为TAG [my2:hello]加载标记处理程序类[null]
今天练习jsp自定义标签的时候,等我写好全部和检查万无一失的时候.执行然后报错了 无法为TAG [my2:hello]加载标记处理程序类[null] 我反复检查代码,发现代码也没什么问题.后面通过百度 ...
- C#实现网页加载后将页面截取成长图片 | Playwright版
前言 如何将网页生成预览图? 要实现这个功能,可以用WebBrowser组件模拟浏览器,或者使用系统浏览器访问网页,再进行截图操作. 但是,这样需要编写大量的控制代码. 工欲善其事,必先利其器! 利用 ...
- AppList.json文件为空,主界面清缓存后加载后还正常显示
问题: AppList.json文件为空,主界面清缓存后加载后还正常显示? 解决: 清缓存后运行不行的话,SelectService中加debugger运行试试.
- tomcat上传文件,重新加载后删除以及在web.xml中配置全局路径
<context-param><param-name>linux_direct</param-name><param-value>/u01/app/be ...
- 文档已完成加载后执行document write整个 HTML 页面将被覆盖
看js文档输出时这样警告: "请使用 document.write() 仅仅向文档输出写内容.如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖" ...
- [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。
学习asp.net mvc 时在更新实体进行SaveChanges()的时候出现了异常,异常如下: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 Object ...
最新文章
- Python实战之logging模块使用详解
- C++面向对象模型初探
- 《小学生C++趣味编程》 第23课 打车费用
- js delete删除对象属性,delete删除不了变量及原型链中的变量
- 【伙伴故事】一盏智能灯,点亮家庭和工业照明的新未来
- 03-28 弱网测试
- Linux工作笔记034---linux tail命令详解_linux在vi中查找字符串
- python实现文件重命名_基于python实现复制文件并重命名
- QTP11 5 HP UFT 11 5 下载地址
- python爬取网易云音乐飙升榜音乐,网易云音乐-飙升榜歌曲信息爬取
- 什么是反馈电路?反馈有什么作用?
- CAD快捷键怎么恢复默认设置?
- Kuma初步学习笔记-universal 模式
- 快速入门spring data jpa 2,多表操作,逻辑删除
- 各大搜索引擎收录入口
- 迪拜国际学术城各所大学中国学生入学人数持续增长
- 51nod 1526 分配笔名(字典树)
- Python curses使用
- Android 文字测量
- 删除Windows服务