内存优化一直是一个很重要但却缺乏关注的点,内存作为程序运行最重要的资源之一,需要运行过程中做到合理的资源分配与回收,不合理的内存占用轻则使得用户应用程序运行卡顿、ANR、黑屏,重则导致用户应用程序发生 OOM(out of memory)崩溃。在你认真跟踪下来可能会发现内存出现问题的地方仅仅只是一个表现的地方,并非深层次的原因,因为内存问题相对比较复杂,它是一个逐渐挤压的过程,正好在你出现问题的代码那里爆了,所以针对应用的内存问题开发者必须多加关注。
三种内存问题进行优化处理: OOM
Out of memory, 内存溢出,当应用申请内存发现超出了JVM的最大限制时候,就会抛出内存溢出异常,引发程序崩溃。引发OOM常见原因有:内存泄漏的累积导致无法申请更多内存、创建大内存对象(如大容量数组、载入大的文件、载入大的图片等)。内存泄漏 一个对象的超出了其生命周期,导致JVM无法回收。这样无法回收的对象堆积多了会导致应用可能无法申请到内存进而导致OOM。常见的内存泄漏有:单例持引起的内存泄漏,如单例持有activity、context、view、drawabl等静态变量引起的内存泄漏,如静态变量持有activity、context、view、drawabl等非静态内部类引起的内存泄漏,原因:非静态内部类会隐式持有外部类实例匿名内部类引起的内存泄漏,如handler、线程匿名内部类runnable、callback等资源未释放引起的内存泄漏,如读写文件没有关闭、网络流操作没有关闭、Bitmap没有释放等广播没有及时取消注册内存抖动 内存抖动是因为在频繁的创建、回收对象,引发的频繁GC,进而影响主线程,最终导致卡顿现象。 要知道怎么正确的使用内存,首先需要了解java虚拟机(即JVM)的内存管理机制。
JVM内存管理机制
JVM内存管理机制是通过根搜索算法,在合适的时期检索对象是否可达,当对象不可达时会被回收,如果对象可达则不会被回收。
对象的生命周期
一个对象从创建到销毁回收是其生命周期的表现,在开发阶段我们是可以预测到对象的生命周期范围,什么时候创建什么时候回收,如果没有被正常回收就会引发对象不可被回收导致的内存泄漏。
Android内存分配
内存分配
Android的Heap空间是一个 Generational Heap Memory 的模型,最近分配的对象会存放在 Young
Generation 区域,当一个对象在这个区域停留的时间达到一定程度,它会被移动到 Old Generation ,最后累积一定时间再移动到 Permanent Generation 区域。
Generation GC
系统在Young Generation、Old Generation上采用不同的回收机制。每一个Generation的内存区域都有固定的大小。随着新的对象陆续被分配到此区域,当对象总的大小临近这一级别内存区域的阈值时,会触发GC操作,以便腾出空间来存放其他新的对象。
Java内存分配模型
可达性分析与GCRoots
通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所有的引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的。
GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域内的对象作为GC roots,被GC roots引用的对象不被GC回收。
本文主要是简单的了解部分Android开发中内存优化问题的解析,想要更深入的进阶性能优化问题可以参考《Android性能优化手册》点击可以查看Android性能调优各方面板块。【腾讯文档】Android性能优化解析