如何应对Android面试官->ART和Dalvik概论

前言

本章知识点相对比较简单,主要介绍 Android 中的虚拟机 ART 和 Dalvik,都是概念性的东西,大家记住就好~~

JVM 与 Dalvik

Android 应用程序运行在 Dalvik/ART 虚拟机,并且每一个应用程序对应有一个单独的 Dalvik 虚拟机实例,Dalvik 虚拟机实则也算是一个 Java 虚拟机,只不过它执行的是 dex 文件而不是 class 文件;

Dalvik 虚拟机与 Java 虚拟机都是按照 Java 规范来的,共享有差不多的特性,差别在于两者执行的指令集是不一样的,Dalvik 是基于寄存器的,而 Java 虚拟机是基于堆栈的;

基于栈的虚拟机

每一个运行的线程,都有一个独立的栈。栈中记录了方法调用的历史,每有一次方法调用,栈中便会多一个栈桢。最顶部的栈桢称作当前栈桢,其代表着当前执行的方法。基于栈的虚拟机通过操作数栈进行所有操作;

字节码指令 可以查看这一章 如何应对Android面试官->JVM内存管理、HSDB大揭秘运行时数据区

基于寄存器的虚拟机

什么是寄存器?

寄存器是 CPU 的组成部分。寄存器是有限存贮容量的高速存贮部件,它可以用来暂存指令、数据和地址;

大致的运行流程如下:

  1. CPU 中的程序计数器指向 0 号指令;

  2. 程序计数器从指令集中拿到 0 号指令交给指令寄存器,由指令寄存器转化为 CPU 指令;

  3. load 内存地址为 100 的对应的数据 1;

  4. 然后将其保存到这个 AX 这个数据寄存器中;

  5. load 内存指令为 104 的对应的数据 1;

  6. 然后将其存到这个 BX 这个数据寄存器中;

  7. 将 AX BX 保存到数据使用 ALU(CPU 中的一个算数逻辑单元) 进行运算;

  8. 将运算结果 STORE 到 CX 这个数据寄存器中;

基于寄存器的虚拟机中没有操作数栈,但是有很多虚拟寄存器。其实和操作数栈相同,这些寄存器也存放在运行时栈中,本质上是一个数组。与 JVM 相似,在 Dalvik VM 中每个线程都有自己的 PC 和调用栈,方法调用的活动记录以桢为单位保存在调用栈上。虚拟机寄存器就是想要模拟真实的寄存器的流程,它就是一块内存区域;

与JVM相比,可以发现 Dalvik 虚拟机程序的指令数明显变少了,数据移动次数也明显减少了;

ART 与 Dalvik

它们都是基于寄存器的虚拟机,但是它们两个有什么区别呢?

Dalvik 虚拟机

执行的是 dex 字节码,解释执行,从 Android 2.2版本开始,支持 JIT 编译(Just In Time)在程序运行的过程中进行选择热点代码(经常执行的代码)就行编译或者优化;

ART 虚拟机

是在 Android4.4 引入的一个开发者选项,也是 Android5.0 及更高版本的默认 Android 运行时。ART 虚拟机执行的是本地机器码 。Android 运行时从 Dalvik 虚拟机替换成 ART 虚拟机,并不要求开发者将自己的应用直接编译成本地机器码,APK 仍然是一个包含 dex 字节码的文件;

ART 虚拟机执行的本地机器码从哪里来的?

Dalvik 下应用在安装的过程,会执行一次优化,将 dex 字节码优化成 odex 文件,而 ART 下将应用的 dex 字节码翻译成本地机器码,这个翻译时机也就发生了应用安装的时候。

ART 引入了预先编译机制(Ahead Of Time) 在安装的时候 使用自带的 dex2oat 工具 将 dex 中的字节码编译成本地机器码;

因为 release 版本是在 5.0 引入的 ART 虚拟机以及本地机器码,虽然绕过了解释执行,提高了运行效率,但是带来了安装变慢的问题,这个问题在5.0 6.0 就会导致安装很慢,但是 Android 在 7.0 之后对此进行了优化,采用了混合编译的方式;

AOT 编译

向 C++ 编译过程靠拢的一项技术,当 APK 安装的时候,系统会通过一个名称为 dex2oat 的工具将 apk 中的 dex 文件编译成包含本地机器码的 oat 文件存下来,这样做之后,再程序执行的时候,就可以直接使用已经编译好的机器码加快效率;

JIT 编译

Android 从2.2版本开始支持 JIT 编译,JIT 是在运行时进行字节码到本地机器码的编译,这也是为什么 Java 普通被认为效率比 C++ 差的原因,无论是解释器的解释还是运行过程中即时编译,都比 C++ 编译出的本地机器码执行多了一个耗费时间的过程;

混合编译

  1. 最初安装应用的时候不进行任何 AOT 编译(安装加快了),运行过程中解释执行,对经常执行的方法进行 JIT,经过 JIT 编译的方法将会记录到 Profile 配置文件中(Profile 文件中记录的是代码的信息而不是可执行的代码);
  2. 当设备闲置和充电时,编译守护进程会进行,根据 profile 文件对常用代码进行 AOT 编译。待下次运行时直接使用;

也就说:Android 系统 2.2 之前是 Dalvik 的解释执行,Android 系统 2.2 - 5.0是 Dalvik 的 JIT 编译,Android 系统 5.0 - 6.0是 ART 虚拟机的 AOT 编译,Android 系统 7.0之后是 ART 虚拟机的混合编译;

ART 相对 Dalvik 的垃圾回收有哪些改进?

  1. 将 GC 的停顿由2次改为1次;

  2. 在仅有一次的 GC 停顿中进行并行处理;

  3. 在特殊场景下,对于近期创建的具有较短生命周期的对象消耗更短的时间进行垃圾回收;

  4. 改进垃圾收集的功效,更频繁的执行并行垃圾收集;

  5. 对于后台进程的内存在垃圾回收过程进行压缩以解决碎片化问题;

简历润色

关于这块可以简单写一下,一般面试官也不会深挖;

下一章预告

高级UI系列来了,带你玩转高级UI;

欢迎三连

来都来了,点个关注点个赞吧,你的支持是我最大的动力~~~

相关推荐
Estar.Lee2 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
温辉_xh2 小时前
uiautomator案例
android
工业甲酰苯胺3 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
少说多做3434 小时前
Android 不同情况下使用 runOnUiThread
android·java
Estar.Lee5 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯6 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey7 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!8 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟9 小时前
Android音频采集
android·音视频
小白也想学C10 小时前
Android 功耗分析(底层篇)
android·功耗