Android客户端ART虚拟机 | 青训营笔记

96 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

ART虚拟机

  • ART整体架构

ART可以粗略的划分成两个层级,执行层和runtime层,执行层负责直接面向java代码的产物,来翻译或者编译执行。runtime层则是提供java语法特性和其他一些支撑运行的底层机制。 image.png

01.对象篇

对象篇————对象生命旅程

image.png

类管理——决定一个对象的大小和行为

  • 类主要描述的是一个对象的内存布局和函数信息
  • 内存布局:类成员的大小、类型、和排布
  • 函数信息:主要是需表信息:某个函数定义在当前类函数表的第几个位置因为java是支持继承的,因此类的内存布局和函数虚表需要做继承链全展开以后才能真正确认

类管理————基类Object的秘密 image.png 类 管理————类加载

  • 一个类分配的对象的大小,是由继承链决定的
  • java的类,是在第一次使用的时候,才会进行加载

类管理————内存布局

image.png 类管理————双亲继承

  • 本质上,双亲委派就是人为规划的一个规定,目的是为了保证系统内同一个类的一致性 内存分配————分配器
  • APP的java对象内存分配上是托管vm处理的,并不会直接向操作系统去申请,实际上对OS内存的占有和内存布局,是VM控制的

image.png 内存分配————不同分配器的特点

image.png 内存分配————典型场景

  • 比如bitmap,在Android高版本,就被隐藏到了native,不直接使用虚拟堆

image.png

  • 内存也是一样的道理,少量的零钱,讲的是方便,使用快捷,但是量小。大块的内存动起来慢,要从大池子中取,集中管理。 内存分配————内存碎片
  • ART内存分配的根本原理,还是给使用者在最优的范围内找到一块大小符合的连续内存

image.png 内存回收——两种思路

  • GC:垃圾回收(Garbage Collection),需要定期查找系统内不用的对象,并释放占用的内存
  • RC:引用计数(Reference Counting),指的是对一个对象引用进行计数,多一个引用者,就+1,少一个就-1,为0就释放典型的如IOS的swift就使用RC进行内存管理
  • 内存回收——RC的问题和解决

image.png

RC认不出环引用,因此引入了弱引用和手动标记 image.png 内存回收——ART的引用

  • 强引用:直接持有的引用就是强引用
  • 软引用:内存不够的时候会回收
  • 弱引用:只要触发Gc就会被回收
  • 内存回收——触发GC的条件
  • 我们想要不被预期外的GC导致卡顿,可以适当的预留内存
  • 大小有上限可预期的情况,new一个大数组,可能分配一大堆放到容器里面要好。

image.png 内存回收——GC的方式

  • GC roots的概念:怎么判断哪些内存是有用的那些是没用的?

image.png 内存回收——tracing GC

  • 从roots遍历,所有mark的对象是有holder的,释放掉没有holder的object

image.png 内存回收——copying GC

  • 从roots遍历,把有用的对象拷贝到另一个区域,然后集中释放掉当前区域的内存

image.png 内存回收——ART的做法 image.png 内存回收——回收之后

  • finalize 方法一般用来跟随对象的生命周期,清理掉绑定的native资源

image.png 执行篇 虚拟机的执行方式

  • 这里面解释执行由解释器完成,JIT和OAT采用的是编译之后,此时直接执行的已经是指令了

image.png 虚拟机执行方式——JIT

image.png 虚拟机的执行方式——OAT

  • OAT,和JIT不同,是在程序运行之前,对APK中的函数进行编译

和程序是否运行无关

  • 编译的范围不是以函数为单位,而是以dex为单位
  • 结果会持久化
  1. 虚拟机的执行方式——延迟绑定
  2. 绑定的越迟,动态性越好,性能越差
  3. 绑定的越早,动态性越差,性能越好

image.png 栈管理

  • ART对于解释执行和编译后编译指令采用两种不同的策略
  • 对于解释执行,栈托管到虚拟机完成
  • 对于编译后,压栈处理和native代码是一样的,遵从对应指令集的约定

image.png