Android中关于内存优化的一些事

android studio 下载 | 2018-08-01 08:30

Java对象的生命周期

Java对象的生命周期经历7个阶段,分别是创建阶段、应用阶段、不可见阶段、不可达阶段、收集阶段、终结阶段、对象控件重新分配阶段。

内存回收机制

内存会有三个区域,Yong Generation(年轻代)、Old Generation(年老代)、permanent Generation(持久代)。其中年轻代里面又分为三个区,eden、S0、S1。

内存的处理过程:

1.对象创建后在Eden区域,

2.执行GC时,如果对象仍然存货,则复制到S0区。

3.当S0区满时,改区域存活对象将复制到S1区,然后S0清空,接下来S0和S1角色互换。

4.当第三部达到一定次数后,存活对象将被复制到Old Generation。

5.当这个对象在Old Generation区域挺溜的时间达到一定程度时,它会被移动到Old Generation,最后积累一定时间再移动到Permaent Generation区域,Permaent Generation区域也存放一些静态文件。

GC回收的一些算法

Copying算法:扫描出存活的对象,并复制到一块新的完全未使用的控件中,对应于Young Generation,就是在Eden、FromSpace或ToSpace之间copy。

标记算法:扫描出存活对象,然后再回收未标记的对象,回收后对空出的空间要么合并,要么标记出来便于下次分配,以减少内存碎片带来的损耗。年老代对象存活时间较长较稳定,使用标记算法回收。

1.kGcCauseForAlloc:在分配内存时内存不够情况下引起的GC,这种情况下GC会stop World。Stop World 是由于并发GC时,其他线程都会停止。

2.kGcCauseBackground:当内存达到一定阈值的时候引发GC,这个时候是一个后台GC,不会引起Stop World。

3.kGcCauseExplicit:显示调用时进行的GC,如果ART打开了这个选项,在system.gc时会进行GC。

其他GC注意事项

1.尽量不去显式调用 system.gc() 减少不必要的系统开销,影响应用的流畅度。

2.尽量减少内存泄露,避免OOM。

什么是内存泄露?

java对象有自己的生命周期,当这个对象不需要再使用时,应该完整地走完生命周期,但因为某些原因,对象虽然已经不再使用,仍然在内存中并没有结束整个生命周期,这就意味着这个对象已经泄露了。

GC会选择一些还存活的对象作为内存遍历的根节点 GC Roots,通过对GC Roots的可达性来判断是否需要回收。

Android系统虚拟机的垃圾回收是通过虚拟机GC机制来实现的。GC会选择一些存活的对象作为内存便利的跟节点GC Roots,通过判断GC Roots的可达性来判断是否需要回收,如上图其中 1 2 3 4直接或间接被GC Roots引用链相连,这类对象被认为还需要使用的对象,就不会被回收。5 6 7将会被回收。到那时这里如果Object4 如果不需要使用的话这时候也不会被回收,就属于内存泄露。

常见内存泄露场景以及注意事项

~ 资源型对象未关闭~ 注册对象未注销~ 类的静态变量持有大数据对象 如bitmap~ 费静态内部类的静态实例~ Handler临时性内存泄露~ 容器中的对象没有清理造成的内存泄露

常见注意事项避免内存消耗过多

AutoBoxing自动装箱过程

Integer num=0;

for(int i=0;i<100;i++){     num+=i;}

这段代码每次循环,虚拟机都必须创建一个新的整数对象,并把它加到其他整数对象前面,创建一个新的整数对象,意味着要消耗更多性能。int只有4字节,而Integer对象有16字节。

内容复用

1、有效利用系统自带资源。2、视图复用,如ViewHolder。3、对象池。4、Bitmap对象复用。

使用最优的数据类型

1、当对象的数目在1000以内且特别多访问而删除和插入不高的时候尽量用ArrayMap替代HashMap。2、枚举的最大优点是安全、易读,但是内存消耗是定义常量的三倍以上。可以使用注解方式来检查安全。3、使用IntDef和StringDef检查类型安全。4、LruCache建议使用这个缓存机制,但是既不能分配太大,也不能分配太小。

图片的内存优化

设置位图规格,使用inSampleSize实现位图缩放和压缩。使用缓存机制等。

内存分析工具

Memory Monitor

这个是一个我们开发过程中很常用的内存、CPU、网络的分析工具。

界面很直观,左上角有运行的机型和项目包名,然后最直观的动态图,分别是CPU、Memory、NetWork。点进去可以进入的Memory。

这里可以清晰的看到颜色对应区域占用的内存大小。

通过这两张图 内存的大部分信息都能查阅到。我们在操作APP加载图片等操作时候能看到内存上升、和下降,如果操作APP后发现内存不会下降可能就是我们有些对象没有及时释放,也有可能导致内存泄露。      还有对应的模拟GC,查看时间段具体内存信息以及一段时间的内存追踪等工具可以使用。可以定位到具体的代码行。如下图:

这里有一个Shallow size这个属性的概念:      Shallow size就是对象本身占用内存的大小,不包含其引用的对象。常规对象(非数组)的Shallow size有其成员变量的数量和类型决定。数组的shallow size有数组元素的类型(对象类型、基本类型)和数组长度决定。

Heap Viewrer

如果是Android Studio的话通过Tools->Android->AndroidDevice Monitor找到这个工具。    进入后选择运行APP的包名然后点击update Heap按钮,这时候会在每次gc时展示数据信息,也可以在后面手动GC,如果在操作页面这时候可能会发现小卡顿,因为在GC时,可能导致其他线程停止工作,这时可以清晰看到表中内存信息。