Android

Android性能优化——内存优化

2022-04-15  本文已影响0人  jxiang112

Android分配个应用的大小是有限制,且在设备出厂之后已经确定,单个应用可用的最大内存的配置位于/system/build.prop文件中的dalvik.vm.heapgrowthlimit配置项。
虽然Android使用的JVM具有内存管理(自动回收)的能力,但是对内存使用不当会导致应用出现异常,包括常见的OOM、内存泄漏、内存抖动等引发的崩溃、卡顿等现象。我们一般主要针对这三种内存问题进行优化处理:

要知道怎么正确的使用内存,首先需要了解java虚拟机(即JVM)的内存管理机制。

JVM内存管理机制

JVM内存管理机制是通过根搜索算法,在合适的时期检索对象是否可达,当对象不可达时会被回收,如果对象可达则不会被回收。

对象的生命周期

一个对象从创建到销毁回收是其生命周期的表现,在开发阶段我们是可以预测到对象的生命周期范围,什么时候创建什么时候回收,如果没有被正常回收就会引发对象不可被回收导致的内存泄漏。

哪些对象需要回收

使用根搜索算法GC Root Trace通过一系列名为GC Root的对象作为起点,向下搜索,搜索所经过的路径称为引用链,当一个对象到GC Root没有应用链相连,则表明此对象需要回收。以下是可以作为GC Root的对象:

什么时候回收内存

介绍什么时候回收内存前,先介绍下Android虚拟机的堆块的管理情况,Android虚拟机遵循java虚拟机堆内存分代管理的机制,主要划分为:新生代、老年代,其中新生代又分为1个Eden(新生代)和2个survisor(Eden幸存的对象),eden、survisor内存默认按8:1:1,因为很多对象创建使用过后就会回收,真正存活下来的不会很多,所以给eden分配80%的占比可以有效提升内存使用率,每次使用eden和1个survisor,回收时将存活的复制到另一个survisor中,然后清空eden和survisor,什么时候会回收内存呢?一般是在各个内存分代区内存不足或者内存快满时会触发内存回收即GC。新生代触发的是Minor GC,因为新生代大多数是朝生夕灭,所以Minor GC比较频繁,但速度会比较快;当survisor中内存不足或者存活年龄达到一定在就会将相应的survisor中的对象复制到老年代中,老年代内存回收是Major GC/Full GC,一般都会伴随至少一次的Minor GC,Major GC速度相对比较慢,相比Minor GC可能会慢10倍。

怎么回收对象

新生代使用复制算法,将eden和1个survisor的内存复制到另一个survisor中,接着清空原先的eden和survisor;老年代使用标记—整理算法,即先标记要回收的对象,再把存活的对象移到一段,接着就是清理掉端边界以外的对象。

不论Minor GC还是Major GC在回收内存的时候都会阻塞其它的工作线程,等完成GC之后再恢复工作线程。

内存优化

上面讲述了虚拟机内存管理机制,对应内存的优化有以下建议:

防止内存泄漏
防止内存抖动

内存分析

LeakCannary

项目中依赖LeakCannary库,使用LeakCannary可以检测内存泄漏

Memory Profiler

使用Android Studio的内存分析器可以对内存分析,根据分析结果进行相应的优化
如需打开内存分析器,按以下步骤操作:

打开内存性能分析器后,其界面如下图所示:


memory_profiler.png

1、强制执行垃圾回收按钮
2、选择捕获堆转存heap dump的按钮
3、暂停/跳转到实时内存数据的按钮
4、事件时间轴:显示应用活动状态、用户输入事件(如touch的down/press等)、屏幕旋转事件等
5、内存分类用量统计

捕获堆转储

选择内存分析器中的Capture heap dump,点击下方的Record按钮,就开始捕获堆转储了,可以点击stop结束捕获,结束捕获之后会自动加载捕获到堆转储。下图是捕获到heap dump之后,打开的界面


heap_dump2.png

1、过滤器
这部分主要用于对heap dump的数据进行过滤,过滤我们关注、需要分享的部分,包括

我们应用端一般主要分析view app heap进行分析主堆,排在java层面的内存问题

一般采用采用Arrang by class过滤占用内存占比比较高的类进行分析,Arrang by package根据包名定位自己代码、三方代码的内存问题

2、统计信息

3、创建的对象数其分配内存情况
这部分会列举过滤之后的所有类名、分配的对象数及内存使用情况,包括

4、类实例对象列表及其实例对象的详细信息
在3中点击某一个类,会在下半部分显示此类的所有实例对象的信息,如点击图中的bitmap。
这部分左侧显示类的实例对象列表:实例对象+地址;点击某个实例会在右侧显示此实例内存分配的详细信息,包括:

我们可以在Fields和References中分析,如果发现可以点如可能存在内存泄漏等,可以右键选择Go to Instance显示其实例内存数据;或者选择Jump to source进入此实例对象所在的源码片段。

一般我们使用内存分析器对内存进行分析时,注重点在于:

上一篇 下一篇

猜你喜欢

热点阅读