美文网首页
Android 进阶解密阅读笔记13

Android 进阶解密阅读笔记13

作者: jkwen | 来源:发表于2021-02-25 11:01 被阅读0次

Android 中的虚拟机

在了解 Dalvik 之前,需要对 Java 虚拟机有所了解,书中也通过一个章节对 Java 虚拟机进行了介绍,之前我也读过了「深入理解 Java 虚拟机」有兴趣的可以看看 「深入理解 Java 虚拟机」阅读完结

Dalvik

命名来自于该虚拟机创作者的祖籍地名,从 Android 诞生一直用到 Android 4.4 版本。虽说也叫虚拟机,但它和 Java 虚拟机有本质区别,因为它基于寄存器,JVM 基于栈,它没有遵循 JVM 规范来实现,为的就是更加适用于移动设备。

同时为了适应于移动设备,特殊的地方还有,

  • 采用 dex 文件加载 与 JVM 不同,Dalvik 会将 *.class 文件再经过打包成 dex 文件后再进行加载解释。dex 文件相比于 JVM 的 jar 文件的优点在于提升了class 文件加载以及类查找的速度。一般来说,一个应用程序编译后对应一个 dex 文件,但随着工程的扩大,有可能超过之前的上限(也就是 65535 的问题),可能一个应用程序会对应多个 dex 文件。另外,将 dex 文件改后缀为 jar,是可以解压出里面是一堆 class 文件的,可见 dex 文件和 jar 文件本质没有区别,只是 dex 专门为移动设备量身定制吧。

  • 可同时运行多个进程 在 Android 中一个进程对应一个运行的应用程序,而一个进程就是一个 Dalvik 虚拟机实例。这样独立成进程的目的是为了避免在某个应用出问题时,影响其他应用。Dalvik 虚拟机实例会在创建应用进程时创建,我们知道 Zygote 进程启动是从 app_main.cpp 的 main 方法开始的,从中会调用 ZygoteInit 的 main 方法,在调用 ZygoteInit 的 main 方法之前,会创建加载虚拟机实例。

  • 拥有共享机制 不同应用间可以共享相同的类,拥有更高的效率。(这点不太理解,我觉得应该是这样,比如 A 应用使用了 Retrofit 相关的东西,B 应用也用的话,就会省的加载,直接从 A 应用加载过的地方直接用相关的资源。)

Dalvik 架构

Java 代码经过编译后变成 .class 文件,再经过 Dalvik 内部的 DX 工具打包成 dex 文件,再由类加载器加载,接着解析器对 Dalvik 字节码进行解释,执行。

我们知道 JVM 很大一部分工作在于对内存空间的管理,Dalvik 虚拟机对运行时堆的管理采用了 标记-清除 回收算法。运行时堆被分成 Zygote Space 和 Allocation Space 两部分。Zygote Space 用于管理 Zygote 进程在启动过程中预加载和创建的对象,它不会触发 GC,且是进程间共享的。Allocation Space 是进程间独立的,每个进程都会分到一块 Allocation Space。

在 Android Studio 的 Logcat 里经常会看到一些 GC log,其实就是 Dalvik 虚拟机在进行垃圾收集,具体日志的格式为,

D/dalvikvm: <GC_Reason><Amount_freed>,<Heap_stats>,<External_memory_stats>,<Pause_time>

<> 里的内容分别是,

  • GC 原因

  • GC 释放内存大小

  • 堆的空闲百分比 已用内存/堆的总内存

  • 内存分配,已分配的内存/引起 GC 的阈值

  • 暂停时间

在 Dalvik 早期,每次执行代码都需要通过解释器将 dex 代码编译成机器码,这显然不高效。后来就引入 JIT 即时编译器,对于多次运行的代码(这种代码叫热点代码)会生成本地机器码,这样就不用每次都编译成机器码了。但是每次程序重新启动时,依然需要编译成机器码才行。为了解决这个问题,就有了 ART(Android Runtime)。

ART

我觉得 ART 的出现是技术迭代发展的必然产物,它和 Dalvik 相比主要区别有,

  • 解决了在 Dalvik 运行不高效的问题。 在 ART 中,系统安装应用程序时会进行一次 AOT(ahead of compilation,预编译),这样程序在运行时直接从本地加载事先编译好的机器码,大大提高效率,耗电也降低了。但这样会增加存储空间占用,安装时间会增加,为了中合这个问题,又重新引入了 JIT,安装时编译部分,运行时利用 JIT 编译部分。其实这块的问题本质就是时间和空间的问题,应该说所有算法的本质也就是对这两个维度进行权衡。想要缩短时间就要牺牲空间,想要节省空间就要牺牲时间。

  • ART 支持 64 位,Dalvik 支持 32 位,因此相对来说效率更高。

  • ART 的运行时堆划分不同。 ART 将运行时堆分为 Zygote Space, Allocation Space, Image Space 和 Large Object Space。前面两个和 Dalvik 一样,Image Space 用来存放一些预加载类,Large Object Space 用来分配大对象。

  • ART 的垃圾回收机制不同。 ART 采用了多种 GC 算法,主要是 CMS 族(sticky-CMS, partial-CMS)

在 ART 中,不再像 Dalvik 那样可以经常在 logcat 里看到 GC 日志,它对 GC 操作做了更细致的划分,但 GC 日志的格式还是基本保持不变。

相关文章

网友评论

      本文标题:Android 进阶解密阅读笔记13

      本文链接:https://www.haomeiwen.com/subject/vydsfltx.html