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 加载后的类存在的期限相关推荐

  1. SpringMVC几个核心类(控制器核心类,加载配置文件核心类,处理url影射核心类,处理视图资源核心类,方法动态调用核心类)

    核心类 制器核心类: •org.springframework.web.servlet.DispatcherServlet  - 配置web.xml   加载配置文件核心类: •org.springf ...

  2. 页面加载后如何使JavaScript执行?

    我正在使用<head>内的<script>执行外部脚本. 现在,由于脚本是在页面加载之前执行的,因此我无法访问<body> . 在文档"加载"后 ...

  3. springboot 启动分析【难点】——如何自动扫描 @SpringBootApplication||如何加载自动配置类 @EnableAutoConfiguration||如何加载前端控制器

    springboot 启动分析[难点] 自动扫描的特点 默认扫描与 启动类 同级的所有包及其子包都可以自动扫描 如果不可要使用@ComponentScan(basePackage={"&qu ...

  4. 自定义标签报 无法为TAG [my2:hello]加载标记处理程序类[null]

    今天练习jsp自定义标签的时候,等我写好全部和检查万无一失的时候.执行然后报错了 无法为TAG [my2:hello]加载标记处理程序类[null] 我反复检查代码,发现代码也没什么问题.后面通过百度 ...

  5. C#实现网页加载后将页面截取成长图片 | Playwright版

    前言 如何将网页生成预览图? 要实现这个功能,可以用WebBrowser组件模拟浏览器,或者使用系统浏览器访问网页,再进行截图操作. 但是,这样需要编写大量的控制代码. 工欲善其事,必先利其器! 利用 ...

  6. AppList.json文件为空,主界面清缓存后加载后还正常显示

    问题: AppList.json文件为空,主界面清缓存后加载后还正常显示? 解决: 清缓存后运行不行的话,SelectService中加debugger运行试试.

  7. tomcat上传文件,重新加载后删除以及在web.xml中配置全局路径

    <context-param><param-name>linux_direct</param-name><param-value>/u01/app/be ...

  8. 文档已完成加载后执行document write整个 HTML 页面将被覆盖

    看js文档输出时这样警告: "请使用 document.write() 仅仅向文档输出写内容.如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖" ...

  9. [Asp.net mvc]实体更新异常:存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。

    学习asp.net mvc 时在更新实体进行SaveChanges()的时候出现了异常,异常如下: 存储区更新.插入或删除语句影响到了意外的行数(0).实体在加载后可能被修改或删除.刷新 Object ...

最新文章

  1. Python实战之logging模块使用详解
  2. C++面向对象模型初探
  3. 《小学生C++趣味编程》 第23课 打车费用
  4. js delete删除对象属性,delete删除不了变量及原型链中的变量
  5. 【伙伴故事】一盏智能灯,点亮家庭和工业照明的新未来
  6. 03-28 弱网测试
  7. Linux工作笔记034---linux tail命令详解_linux在vi中查找字符串
  8. python实现文件重命名_基于python实现复制文件并重命名
  9. QTP11 5 HP UFT 11 5 下载地址
  10. python爬取网易云音乐飙升榜音乐,网易云音乐-飙升榜歌曲信息爬取
  11. 什么是反馈电路?反馈有什么作用?
  12. CAD快捷键怎么恢复默认设置?
  13. Kuma初步学习笔记-universal 模式
  14. 快速入门spring data jpa 2,多表操作,逻辑删除
  15. 各大搜索引擎收录入口
  16. 迪拜国际学术城各所大学中国学生入学人数持续增长
  17. 51nod 1526 分配笔名(字典树)
  18. Python curses使用
  19. Android 文字测量
  20. 删除Windows服务

热门文章

  1. 基于稀疏和HOG特征的人耳识别(代码)
  2. 网站上数字证书原理你知道么?
  3. 机器人方向与高考选专业的一些误区
  4. pytz 将date确定时区后转换成任意时区
  5. 音频之手机物理按键(Exynos7872)
  6. 在3D建模中,ZBrush中的道具雕刻【案列教程】
  7. 计算机课实践心得体会,【计算机实习心得】_计算机实习心得体会
  8. 测试AVFrame的空间分配和引用计数接口
  9. springboot相比spring的优势
  10. 树形DP——HDU 1011 Starship Troopers