这是我参与「第四届青训营 」笔记创作活动的第19天
ART虚拟机
ART整体架构
对象篇
- 对象是谁 -- 类的管理
- 对象从哪里来 -- 内存分配
- 对象到哪里去 -- 内存回收
对象的生命旅程
对象分配
- 分配多大 -- 类
- 类主要描述的是一个对象的内存布局和函数信息
- 内存布局:类成员的大小、类型、排布
- 函数信息:虚表的信息:某个函数定义在当前函数表的第几个位置,由于java支持继承,因此类的内存布局和函数虚表需要做继承链全展开后才能真正确认(这也是动态性的来源)
- 怎么分配 -- 内存管理
- APP的java对象内存分配上是托管到VM来处理的,并不会直接向操作系统去申请,实际上对OS内存的占用和内存布局由VM控制(预留-扩展)
- 分配方式
- TLAB:临时变量(小量内存)
- ROSallocator:数组/容器(中等内存)
- LOSallocator:bitmap储存图片(大量内存)
- 内存碎片:多次分配后内存被分割成多个小块
对象销毁(内存回收)
-
GC(垃圾回收):定期查找系统内不用的对象,并且释放占用的内存
- 触发条件:
- 没内存了
- 手机认为该GC了:VM堆达到占用水位、系统内存紧张、经济性策略
- GC判断方式:
- 主要思路:不能被释放:栈、static变量、native ref、VM保留
- tracing GC:从roots遍历,所有mark的对象是由holder的,释放没有holder的object
- copying GC:从roots遍历,把有用的对象拷贝到另一个区域,然后集中释放之前区域的内存(好处:得到的内存空间是连续的)
- 触发条件:
-
RC(引用计数):对一个对象引用进行技术,多一个引用者就+1,少一个就-1,为0时释放
-
引用的等级
- 强引用:直接持有
- 软引用:内存不够时就会回收
- 弱引用:只要触发GC就会被回收
执行篇
-
搬砖的姿势 -- 虚拟机的执行方式
- 解释执行:dex code
- JIT:解释执行时给每一个函数生成一个profile文件,每次执行此函数会打分,分够了就提交给JIT编译器,JIT编译器编译后执行OST替换,下一次执行就用JIT执行而不是解释执行
- OAT(AOT):与JIT的不同之处:
- OAT在程序运行前对APK中的函数进行编译
- 编译范围不是以函数为单位,而是以dex为单位
- AOT的产物会持久化
-
开始和结束 -- 栈管理
- ART对于解释执行和编译后指令采取两种不同的策略:
- 对于解释执行的,栈托管到虚拟机完成
- 对于编译后的,压栈处理和native代码是一样的,遵从对应指令集的约定
- ART对于解释执行和编译后指令采取两种不同的策略:
-
高效的执行 -- 多线程
-
Object类中有shadow monitor成员,当对一个对象使用了sync是,此对象会生成一个lock指针保存在shadow monitor指向的内存地址中
-
胖锁和瘦锁:ART有这两种锁,monitor一开始会生成瘦锁
- 瘦锁:不断地轮询对方好了没 -- 费劲但响应快,实际上采用spinlock
- 胖锁:完成了再通知锁 -- 省力但反应慢,实际上采用mutelock
- 一开始是瘦锁,当发现等待时间太多了就会转成胖锁
-