这是我参与「第四届青训营 」笔记创作活动的第9天
打开ART虚拟机的大门
本堂课内容
- 对象
- 对象是谁——类的管理
- 对象从哪里来——内存分配
- 对象到哪里去——内存分配
- 执行
- 虚拟机的执行方式
- 栈管理
- 多线程
知识点介绍
对象
对象的生命历程
- 对象分配(分配多大类、怎么分配?)
- 对象使用(执行类的方法、访问对象成员)
- 对象销毁(内存回收)
类管理
这是决定一个对象的大小和行为
类主要描述的是一个对象的内存布局和函数信息
通过查看java源码,可以看出Object基类的定义:
public class Object{
private transient Class<?> shadow$__klass_;
private transient int shadow$_monitor_;
}
类加载
一个类分配的对象大小,是由继承链决定的,JAVA的类是在第一次使用的时候才会进行加载
双亲继承
本质上,双亲委派就是一个认为划定的一个规矩,目的是为了保证系统内同一个类的一致性
抽象继承的好处
合理的抽象,会让定义对象属性的时候变得更加优雅
内存分配
APP的java对象内存分配上是托管到虚拟机来处理的,并不会直接向操作系统去申请,实际上对OS内存的占用和内存布局是虚拟机来决定的
内存分配的一些典型场景
少量的内存使用便捷,但是内存的量小;大块的内存使用时候需要从大池子里面取,使用的时候比较慢
ART的内存分配的根本原理,还是给使用者在最优的范围内找到一块大小符合的连续内存
内存碎片
我们在使用内存的时候希望的是可用内存尽可能的连续起来,在回收内存后尽量少的产生内存碎片
内存回收
- GC:垃圾回收,需要顶起查找系统内不用的对象,并且释放占用的内存
- RC:引用计数,指的是对一个对象引用进行计数,多一个引用者就+1,少一个就-1,为0就释放
ART的引用
强引用就是引用,是直接持有的
软引用是内存不够的时候会回收
弱引用是只要出发GC就会被回收
触发GC的条件
-
没内存的时候就会触发GC
-
系统判断到应该GC了,就会触发GC
场景有:VM堆占用达到水准,系统内存紧张,想触发了
IOS使用的内存少的原因
同样是三个APP,IOS的每个app内存空间里面都是只有在用内存,不存在浪费
GC的判断方式
怎么判断哪些内存是有用的,哪些是没用的;
从roots遍历,所有mark的对象是有holder的,最后再释放掉没有holder的object,这种方式叫做tracing GC
从roots遍历,把有用的对象拷贝到另一个区域,然后集中释放的掉当前区域中的内存空间,这种方式叫做copying GC
ART的做法
| 前台GC | 后台GC | |
|---|---|---|
| 使用场景 | 应用在前台的进程 | 非前台应用进程 |
| 算法 | trancing GC | copying GC |
| 速度 | 快 | 慢 |
| 内存碎片 | 有 | 无 |
| 额外空间 | 不需要 | 需要 |
执行
执行方式
- 解释执行——dex code
- JIT——JIT code
- AOT——AOT code
JIT的OSR就是栈上替换,在某些分支可以采用更激进的优化,处理不了还能回退
OAT
与JIT不同的是,在程序运行之前,对APK中的函数进行编译
- 和程序是否运行无关
- 编译的范围不是以函数为单位的,而是以dex为单位的
- 结果会持久化
虚拟机的执行方式——延迟绑定
绑定的越迟——动态性越好,性能越差
绑定过越早——动态性越差,性能越好
栈管理
ART对于解释执行和编译后指令采用两种不同的策略
- 对于解释执行,栈托管到虚拟机完成
- 对于编译后的,压栈处理和native代码一样,遵循指令集的约定
异常处理
发生异常现象的时候也会产生回栈的现象
多线程和同步
java引入了sync机制,让加锁和解锁变得很方便
瘦锁费劲但是响应快,实现上采用spinlock
胖锁省力但是反应慢,实现上采用mutexlock
个人总结
本章简单的了解了的有关ART虚拟机的相关知识,由于涉及到许多虚拟化以及操作系统的知识,感觉对于这部分的理解是在不是很透彻,需要课下结合老师推荐的两本数目慢慢的消化消化