内存优化
在 Android 系统中有个垃圾内存回收机制,在虚拟机层自动分配和释放内存,因此不需要在代码中分配和释放某一块内存,从应用层面上不容易出现内存泄漏和内存溢出等问题,但是需要内存管理
Android 系统在内存管理上有一个 Generational Heap Memory 模型,内存回收的大部分压力不需要应用层关心,Generational Heap Memory 有自己一套管理机制,当内存达到一个阈值时,系统会根据不同的规则自动释放系统认为可以释放的内存
也正是因为 Android 程序把内存控制的权力交给了 Generational Heap Memory,所以一旦出现内存泄漏和溢出方面的问题,排查错误将会成为一项异常艰难的工作
除此之外,部分 Android 应用开发人员在开发过程中并没有特别关注内存的合理使用,也没有在内存方面做太多的优化,当应用程序同时运行越来越多的任务,加上越来越复杂的业务需求时,完全依赖 Android 的内存管理机制就会导致一系列性能问题逐渐呈现,对应用的稳定性和性能带来不可忽视的影响
因此,解决内存问题和合理优化内存是非常有必要的
Android 内存管理机制
Android 应用都是在 Android 的虚拟机上运行,应用程序的内存分配与垃圾回收都是由虚拟机完成的;在 Android 系统,虚拟机有两种运行模式:Dalvik 和 ART
Java 对象生命周期
一般 Java 对象在虚拟机上有7个运行阶段:
- 创建阶段->应用阶段->不可见阶段->不可达阶段->收集阶段->终结阶段->对象空间重新分配阶段
内存分配
在 Android 中,内存分配实际上是对堆的分配和释放;当一个 Android 程序启动,应用进程都是从一个叫做 Zygote 的进程衍生出来,系统启动 Zygote 进程后,为了启动一个新的应用程序进程,系统会衍生 Zygote 进程生成一个新的进程,然后在新的进程中加载并运行应用程序的代码
- 其中,大多数的 RAM pages 被用来分配给 Framework 代码,同时促使 RAM 资源能够在应用所有进程之间共享
但是为了整个系统的内存控制需要,Android 系统会为每一个应用程序都设置一个硬性的 Dalvik Heap Size 最大限制阈值,整个阈值在不同设备上会因为RAM大小不同而有所差异
- 如果应用占用内存空间已经接近整个阈值时,再尝试分配内存的话,就很容易引起内存溢出的错误
内存回收机制
我们需要知道的是,在 Java 中内存被分为三个区域:Young Generation(新生代)、Old Generation(年老代)、Permanent Generation(持久代);最近分配的对象会存放在 Young Generation 区域。对象在某个时机触发GC回收垃圾,而没有回收的就根据不同规则,有可能被移动到 Old Generation,最后累积一定时间在移动到Permanent Generation 区域
系统会根据内存中不同的内存数据类型分别执行不同的 GC 操作:
- GC 通过确定对象是否被活动对象引用来确定是否收集对象,进而动态回收无任何引用的对象占据的内存空间
- 需要注意的是频繁的 GC 会增加应用的卡顿情况,影响应用的流畅性,因此需要尽量减少系统 GC 行为,以便提高应用的流畅度,减小卡顿发生的概率
内存分析工具
做内存优化前,需要先了解当前应用的内存使用现状,通过现状去分析哪些数据类型有问题,各种类型的分布情况如何,以及在发现问题后如何发现是哪些具体对象导致的,这就需要相关工具来帮助我们
Memory Monitor
Memory Monitor 是一款使用非常简单的图形化工具,可以很好地监控系统或应用的内存使用情况,主要有以下功能:
- 显示可用和已用内存,并且以时间为维度实时反应内存分配和回收情况
- 快速判断应用程序的运行缓慢是否由于过度的内存回收导致
- 快速判断应用是否由于内存不足导致程序崩溃
Heap Viewer
Heap Viewer 的主要功能是查看不同数据类型在内存中的使用情况:
- 当前进程中的 Heap Size 的情况
- 分别有哪些类型的数据
- 各种类型数据占比情况
通过分析这些数据来找到大的内存对象,再进一步分析这些大对象,进而通过优化减少内存开销,也可以通过数据的变化发现内存泄漏
Allocation Tracker
Memory Monitor 和 Heap Viewer 都可以很直观且实时地监控内存使用情况,还能发现内存问题,但发现内存问题后不能再进一步找到原因,或者发现一块异常内存,但不能区别是否正常,同时在发现问题后,也不能定位到具体的类和方法
这时就需要使用另一个内存分析工具 Allocation Tracker,进行更详细的分析,Allocation Tracker 可以分配跟踪记录应用程序的内存分配,并列出了它们的调用堆栈,可以查看所有对象内存分配的周期
Memory Analyzer Tool(MAT)
MAT 是一个快速,功能丰富的 Java Heap 分析工具,通过分析 Java 进程的内存快照 HPROF 分析,从众多的对象中分析,快速计算出在内存中对象占用的大小,查看哪些对象不能被垃圾收集器回收,并可以通过视图直观地查看可能造成这种结果的对象
常见内存泄漏场景
如果在内存泄漏发生后再去找原因并修复会增加开发的成本,最好在编写代码时就能够很好地考虑内存问题,写出更高质量的代码,这里列出一些常见的内存泄漏场景,在以后的开发过程中需要避免这类问题。
- 资源性对象未关闭: 比如 Cursor、File 文件等,往往都用了一些缓冲,在不使用时,应该及时关闭它们
- 注册对象未注销: 比如事件注册后未注销,会导致观察者列表中维持着对象的引用
- 类的静态变量持有大数据对象
- 非静态内部类的静态实例
- Handler 临时性内存泄漏: 如果 Handler 是非静态的,容易导致 Activity 或 Service 不会被回收
- 容器中的对象没清理造成的内存泄漏
- WebView: WebView存在着内存泄漏的问题,在应用中只要使用一次WebView,内存就不会被释放掉
除此之外,内存泄漏可监控,常见的就是用 LeakCanary 第三方库,这是一个检测内存泄漏的开源库,使用非常简单,可以在发生内存泄漏时告警,并且生成 leak tarce 分析泄漏位置,同时可以提供 Dump 文件进行分析
上边分析了那么多,我们清楚的了解到了内存优化对于 Android 系统的重要性;所以也有人说内存优化是 Android性能优化的发动机,照上述所讲的来看,这一点也不为过吧;有需要了解更多关于 Android 性能优化 相关资讯的朋友;可点击此处查看获取方式 或者简信发送 "性能" ,即可获取一张 Android 性能优化思维导图及配套的一份学习手册,以便大家能够更好的学习 Android 性能优化
Android 性能优化思维导图
Android 性能优化学习手册
好了,以上就是今天要分享的内容,大家觉得有用的话,可以点赞分享一下;如果文章中有什么问题欢迎大家指正;欢迎在评论区或后台讨论哈~
网友评论