只能硬件设备当前的性能导致很多开发者 开始不再关注内存处理相关,其实这是有问题的,目前的智能设备就相当于一个app的大盒子,如果每个app的开发者都不关心内存消耗的话那智能设备就会出现越用越卡的情况出现
说到Android的内存优化,不得不提到java虚拟机的内存优化。因为目前主流的app还是基于java或者kotlin这样的基于虚拟机的语言来开发的。所以本文还是基于java虚拟机的内存优化
内存泄露的内存主要指的是对象的内存,也就是虚拟机的堆内存,内存泄漏的概念区分于oom,oom是app使用的堆内存超过系统分配的内存以后,系统对app进行异常回收并退出的情况,而内存泄露指的是存在不需要继续被使用(Gc root 已经断开)但是还一直占用内存的对象存在
说到内存优化,自然我们需要一些比较厉害的工具来辅助我们生产一些指标或者查找可能造成内存泄露的原因定位
公司里分析内存泄露和内存溢出的常用步骤大概如下
使用LeakCanary进行初步排查;
使用Android studio自带的Android Profiler分析;
使用MemoryAnalyzer(MAT)详细分析;
我们这里就大概讲一下常用的分析工具的使用
Square公司,可以直接在手机端查看内存泄露的工具本质上还是用命令控制生成hprof文件分析检查内存泄露。通过如下明细的提示可以快速定位到内存泄露的点
源码地址:https://github.com/square/leakcanary
内存泄露分析:
https://square.github.io/leakcanary/fundamentals/
代码引用:
// debugImplementation because LeakCanary should only run in debug builds.
debugImplementation ‘com.squareup.leakcanary:leakcanary-android:2.0-beta-3’
application的onCreate LeakCanary.install(this);
Heap SnapShot 是as集成的分析内存泄露的工具
首先在Profiler中对某一顿可能存在内存泄露的地方进行标识,生成如下图的Heap Dump点击图标进行保存hprof文件
生成hprof文件以后直接点击这个按钮即可
该面板里的信息可以有三种类型:app heap/image heap/zygote heap.
分别代表app 堆内存信息,图片堆内存信息,zygote进程的堆内存信息。
具体展开面板以后的内容如下可以根据具体的情况具体分析 ,如一段时间内的内存分配情况,引用情况等
下载地址:http://eclipse.org/mat/downloads.php
MAT工具全称为Memory Analyzer Tool,一款详细分析Java堆内存的工具,该工具非常强大,为了使用该工具,我们需要hprof文件可以通过上面的Heap Snapshot工具来生成并保存到本地。但是该文件不能直接被MAT使用,需要进行一步转化,可以使用hprof-conv命令来转化,Android Studio可以直接右键到处为标准的hprof文件
我们常用android studio 生成hprof文件并右键转化为标准的可用做mat分析的文件,通过下图的export按钮可以获取分析阶段的hprof文件
转换为标准的.hprof文件
Overview 视图该视图会首页总结出当前这个Heap dump占用了多大的内存,其中涉及的类有多少,对象有多少,类加载器,如果有没有回收的对象,会有一个连接,可以直接参看(图中的Unreachable Objects Histogram)。
histogram视图主要是查看某个类的实例个数,比如我们在检查内存泄漏时候,要判断是否频繁创建了对象,就可以来看对象的个数来看。也可以通过排序看出占用内存大的对象
Dominator tree视图以占用总内存的百分比来列举所有实例对象,注意这个地方是对象而不是类了,这个视图是用来发现大内存对象的。这些对象都可以展开查看更详细的信息,可以看到该对象内部包含的对象
这个视图会展示一些可能的内存泄漏的点,比如上图上图显示有3个内存泄漏可疑点,我们以Problem Suspect 1为例来理解该报告,首先我们来看该可疑点详细信息
上面信息显示ImageCahe类的一个实例占用了14.19%的内存,具体值为5147200字节(5147200/1024/1024=4.9M),并存放在LinkedHashMap这个集合中,然后我们点击Details跳转到更详细的页面这样就可以很快的分析到内存泄露的点
该工具是android sdk 工具中Monitor的一个分析堆内存使用情况的工具,使用此工具可以检测堆内存使用情况及分析是否存在内存泄露和内存抖动的问题,也可以手动触发Gc
参数 | 含义 |
---|---|
Heap Size | 堆分配给App的内存大小 |
Allocated | 已分配使用的内存大小 |
Free | 空闲的内存大小 |
%Used | Allocated/Heap Size,使用率 |
Objects | 对象数量 |
Heap Viewer中的数值会自动在每次发生GC时会自动更新,那么我们是等着他自己GC么?既然我们是来看内存泄漏,那么我们在需要检测内存泄漏的用例执行过后,手动GC下,然后观察data object一栏的total size(也可以观察Heap Size/Allocated内存的情况),看看内存是不是会回到一个稳定值,多次操作后,只要内存是稳定在某个值,那么说明没有内存溢出的,如果发现内存在每次GC后,都在增长,不管是慢增长还是快速增长,都说明有内存泄漏的可能性。
因为内存抖动的时候,会频繁发生GC,这个时候我们只需要开启Heap Viewer,观察数据的变化,如果发生内存抖动,会观察到数据在段时间内频繁更新
TraceView也是Monitor下面的一个工具,只不过它是用来分析方法频繁调用和执行耗时的
从代码层面分析性能问题,针对每个方法来分析,比如当我们发现我们的应用出现卡顿的时候,我们可以来分析出现卡顿时在方法的调用上有没有很耗时的操作,关注以下两个问题:
简单一点来说就是我们使用这个工具能找到频繁被调用的方法,也能找到执行非常耗时的方法,前者可能会造成Cpu频繁调用,手机发烫的问题,后者就是卡顿的问题
上下两部分面板分别为上面部分为线程及对应的方法执行时间线;下面部分为分析面板
名称 | 释义 |
---|---|
Incl Cpu Time | Cpu执行该方法该方法及其子方法所花费的时间 |
Incl Cpu Time % | Cpu执行该方法该方法及其子方法所花费占Cpu总执行时间的百分比 |
Excl Cpu Time | Cpu执行该方法所话费的时间 |
Excl Cpu Time % | Cpu执行该方法所话费的时间占Cpu总时间的百分比 |
Incl Real Time | 该方法及其子方法执行所话费的实际时间,从执行该方法到结束一共花了多少时间 |
Incl Real Time % | 上述时间占总的运行时间的百分比 |
Excl Real Time % | 该方法自身的实际允许时间 |
Excl Real Time | 上述时间占总的允许时间的百分比 |
Calls+Recur | 调用次数+递归次数 |
Calls/Total | 调用次数和总次数的占比 |
Cpu Time/Call | Cpu执行时间和调用次数的百分比,代表该函数消耗cpu的平均时间 |
Real Time/Call | 实际时间于调用次数的百分比,该表该函数平均执行时间 |
AndroidStudio 的功能之一 可以非常细化的分析出代码的一些潜在问题,同时也包括无效资源等