android 内存优化

时间:2024-04-22 16:33:53

一、内存需要优化的几个点

什么是内存抖动?

在Java中,每创建一个对象,就会申请一块内存,存储对象信息;每分配一块内存,程序的可用内存也就少一块;当 程序被占用的内存达到一定临界程度,GC 也就是垃圾回收器(Garbage Collector)就会出动,来释放掉一部分不再 被使用的内存。 这本身没有问题,但是当频繁创建对象就会造成内存不断地攀升,在回收了之后又迅速涨起来,接 着又一次的回收。在短时间内反复地发生内存增长和回收,这就是内存抖动(Memory Churn)。

内存抖动能带来什么问题?

卡顿

内存的回收在Java当中采用的是GC机制,无论是何种方式实现的GC在执行的时候都不可避免的需要 STW(Stop The World) 。STW意味着我们所有的工作线程都将会被暂停,虽然这个时间很短,但终究是有时间成本的。一两 次内存回收不容易被用户察觉,但多次内存回收行为集中在短时间内爆发,这就造成了比较大的界面卡顿的风险。 例如当用户点击某个按钮,或者在界面中进行滑动时,此时虚拟机在运行GC线程,进行内存回收,那响应用户点击 事件的线程就被GC暂停了,只能在恢复后才能响应,因此给到用户最直观的感受就是程序卡了。

OOM

内存抖动除了可能造成卡顿之外,也可能会造成内存溢出(OOM)。这是因为如果垃圾回收的实现采用的是标记-清除 算法,那么此算法可能导致大量的内存碎片。那这些无法连续的空间小,如果我们申请比较大的空间,会导致这些小内存块不能被利用,从而产生OOM。

什么是内存泄漏?

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的 浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 在Java中,就是该释放的对象无法被释放,那这些对象将一 直内存,最终导致程序可用内存越来越少,直至无内存可用(OOM)。

二、内存优化的工具

详细造成内存泄漏的请移步下一篇android内存优化-内存泄漏

android profile

这个工具在Android Studio上集成,使用也很简单,本篇不做赘述。

LeakCanary

我们重点说一下LeakCanary。

LeakCanary是一个基于MAT(一种数据结构)进行Android应用程序内存泄漏自动化检测的的开源工具,我们可以通过集成LeakCanary提供的jar包到自己的工程中,一旦检测到内存泄漏,LeakCanary就会dump Memory信息,并通过另一个进程分析内存泄漏的信息并展示出来,随时发现和定位内存泄漏问题。

LeakCanary的工作原理

RefWatcher.watch() 创建一个 KeyedWeakReference 到要被监控的对象。
然后在后台线程检查引用是否被清除,如果没有,调用GC。
如果引用仍然没有被清除,把 heap 内存 dump 到 APP对应的文件系统中的一个 .hprof 文件中。在另外一个独立进程中开启一个 HeapAnalyzerService ,里面有一个HeapAnalyzer 使用HAHA(对有向图的顶点排成一个线性序列) 开源库解析指定时刻的堆栈快照文件heap dump。
从heap dump中,得益于唯一的 reference key, HeapAnalyzer 找到KeyedWeakReference,定位内存泄露的引用。
HeapAnalyzer 计算到 GC roots的最短强引用路径,并确定是否是泄露。如果是的话,建立导致泄露的引用链。
引用链结果传递到 APP 进程中的DisplayLeakService, 并以通知的形式展示出来。

官方的原理简单来解释就是这样的:在一个Activity执行完onDestroy()之后,将它放入WeakReference中,然后将这个WeakReference类型的Activity对象与ReferenceQueque关联。这时再从ReferenceQueque中查看是否有没有该对象,如果没有,执行gc,再次查看,还是没有的话则判断发生内存泄露了。最后用HAHA这个开源库去分析dump之后的heap内存。

LeakCanary在android studio中的使用,本文暂不赘述。