前言
很高兴遇见你~
内存优化一直是 Android 开发中的一个非常重要的话题,他直接影响着我们 app 的性能表现。但这个话题涉及到的内容很广且都偏向底层,让很多开发者望而却步。同时,内存优化更加偏向于“经验知识”,需要在实际项目中去应用来学习。
因而本文并不想深入到底层去讲内存优化的原理,而是着眼于宏观,聊聊 android 是如何分配和管理内存、在内存不足的时候系统会如何处理以及会对用户造成什么样的影响。
Android 应用基于 JVM 语言进行开发,虽然 google 根据移动设备特点开发了自家的虚拟机如 Dalvik、ART,但依旧是基于 JVM 模型,在堆区分配对象内存。因此 Java heap(java 堆)是android应用内存分配和回收的重点。其次,移动设备的 RAM 非常有限,如何为进程分配以及管理内存也是重中之重。
文章的主要内容是分析 Java heap、RAM 的内存管理,以及当内存不够时 android 会如何处理。
那么,我们开始吧。
Java Heap
Java Heap,也就是 JVM 中的堆区。简单回顾一下 JVM 中运行时数据区域的划分:
![image.png](https://i-blog.csdnimg.cn/blog_migrate/e8d254b22b7e8fed1fcb3b58890b5e73.png)
- 橙色区域的方法栈以及程序计数器属于线程私有,主要存储方法中的局部数据。
- 方法区主要存储常量以及类信息,线程共享。
- 堆区主要负责存储创建的对象,几乎一切对象的内存都在堆区中分配,同时也是线程共享。
我们在 android 程序中使用如 Object o = new Object()
代码创建的对象都会在堆区中分配一块内存进行存储,具体如何分配由虚拟机解决而不需要我们开发者干预。当一个对象不再使用时, JVM 中具有垃圾回收机制(GC),会自动释放堆区中无用的对象,重新利用内存。当我们请求分配的内存已经超过堆区的内存大小,则会抛出 OOM 异常。
在 android 中,堆区是一个由 JVM 逻辑划分的区域,他并不是真正的物理区域。堆区并不会直接全部映射和他等量大小的物理内存,而是到了需要使用时,才会去建立逻辑地址和物理地址的映射:
![image.png](https://i-blog.csdnimg.cn/blog_migrate/529752a1875b212089ebec83cbbd54de.png)
这样可以给应用分配足够的逻辑内存大小,同时也不必在启动时一次性分配一大块的物理内存。在相同大小的内存中,可以运行更多的程序。
当堆区进程 GC 之后,释放出来多余的空闲内存,会返还给系统,减少物理内存的占用。但这个过程涉及到比较复杂的系统调用,若释放的内存较为少量,可能得不偿失,则无需返还给系统,在堆区中继续使用即可。
在 GC 过程中,如果一个对象不再使用,但是其所占用的内存无法被释放,导致