Android的内存优化必须了解JVM虚拟机的GC
Java虚拟机
Java虚拟机是一台“抽象的计算机”,它拥有自己的处理器,堆栈,寄存器以及相应指令系统;Java虚拟机屏蔽了与具体操作系统相关的平台信息,使得Java程序只需要生成在该虚拟机运行的目标代码,就可以在多平台上运行;虽然叫Java虚拟机,但在它之上运行的语言不仅又Java,kotlin,Groovy,Scala等都可以运行;
编译时环境
Activity.java
|
Java编译期
|
Activity.Class
运行时环境
Activity.class
|
Java虚拟机
Java虚拟机运行时数据区域
- 方法区
- Java虚拟机栈
- 本地方法栈
- Java堆
- 程序计数器
详情参考改文章:JVM 内存结构
垃圾回收(GC)
强/软/弱/虚引用
- 强引用:当新建对象为强引用时,垃圾回收器绝对不会回收它,宁愿抛出OutofMemoryError异常,让程序异常终止也不会回收;
- 软引用:当新建的对象为软引用时,当内存不够时,回收器就会回收这些对象,如果回收后还是没有足够的内存,抛出OutOfMemoryError异常;
- 弱引用:当新建对象为弱饮用时,垃圾回收器不会管当前内存事发后足够,都会回收它的内存;
- 虚引用:虚引用跟其他引用都不同,如果一个对象仅持有虚引用,在任何时候都可能被GC回收,只是当它被回收时会收到一个系统通知。
垃圾标记算法
- 引用计数算法:每一个对象都有一个引用计数器,当对象每被引用一次时加1,引用失效时就减1.当计数为0时则被该对象设置为课回收的“垃圾对象”;缺点:如果两个对象相互引用,会引起内存泄漏
- 根搜索算法:GC Root GC Root 的集合,与GC Root相连的算可达的,与GC Root 集合不相连的算不可达的可以被回收。
GC Root:可以作为GC Root的对象:
1、虚拟机栈中正在引用的对象
2、本地方法栈中正在引用的对象
3、静态属性引用的对象
4、方法区常量引用的对象
垃圾收集算法
- 标记-清除算法:顾名思义,请用根搜索算法标记课回收的对象,之后将标记为“垃圾的对象进行回收”;
- 复制算法:先把内存一分为二,每次只使用其中一个区域,垃圾收集时,将存活的对象全部拷贝到另外一个区域。然后对之前的区域进行全部回收;
- 标记-压缩算法:在标记可回收的对象后,将所有存活的对象压缩到内存的一端,让他们排在一起,然后对边界意外的内存进行回收;
- 分代收集算法:Java堆中存在的对象生命周期又较大差别,大部分生命周期很短,有的很长,甚至与应用程序或者Java虚拟机生命周期一样,因为分代算法就是根据对象的生命周期长短将放到不同的区域;
内存泄漏/溢出/抖动
- 内存泄漏:一个不在被程序使用的对象或变量依旧存活在内存中无法被回收;(比较小的内存泄漏并不影响程序,但是内存泄漏多了,占用内存空间就更大,程序正常需要申请使用的内存则会相应减少;严重就会引起内存溢出)
- 内存溢出:OOM 当程序申请内存时,没有足够的内存供程序使用;
- 内存抖动:通常是指在短时间内发生了多次内存的分配和释放,主要原因则是短时间内频繁的创建对象,为了应对这种情况,虚拟机会频繁的触发GC操作,当GC进行是,其他线程会被刮起等待GC的完成,频繁GC,也就会导致比如UI在绘制时会超过16ms一帧,导致画面卡顿等。