android 内存管理基础知识记录

1. android 基础知识

1.1 Stack and Heap

Stack 栈空间由操作系统控制,其主要存储函数地址、函数参数、局部变量等等。栈内存分配运算内置于处理器的指令集中,运算效率很高。

存在栈中的数据大小与生存区必须是确定的,由于存储数据的特点,栈空间不需要很大,一般为 几 MB 大小。

Heap 堆空间是使用时由程序员控制的,程序员可以使用 malloc、new、free、delete 等函数调用来操作这片地址空间。

堆的优势是可以动态地分配内存大小,生存期也是由我们决定,动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,并立即将指针置位 NULL,防止产生野指针。

Heap 堆区为程序完成各种复杂任务提供内存空间,所以空间一般比较大,为 几百 M 到 几 G。

1.2 进程内存空间与 RAM 的关系

进程的内存空间只是虚拟内存(或者叫做逻辑内存),而程序的运行需要实实在在的内存,即物理内存(RAM)。在必要时,操作系统通过页映射表(page table)的方式将程序运行时申请的内存(虚拟内存)映射到 RAM 中,让进程能够使用物理内存。

RAM 作为进程运行不可或缺的资源,对系统性能和稳定性有着决定性影响。另外,RAM 的一部分被操作系统留作他用,比如显存等等,内存映射和显存等都是由操作系统控制,我们也不必过多地关注。

进程所操作的空间都是虚拟地址空间,无法直接操作 RAM。

内存页映射表示意图如下:

image

1.3 android 中的 naive 进程与 java 进程

(1) native 进程:采用 C/C++ 实现,不包含 dalvik 实例的 Linux 进程,/system/bin/ 目录下的程序文件运行以后都是以 native 进程形式存在的,如 surfaceflinger、init 进程等

(2) Java 进程:实例化了 dalvik 虚拟机实例的 Linux 进程,每一个 android 上的 java 进程实际上就是一个 linux 进程,只是进程中多了一个 dalvik 虚拟机实例。因此,java 进程的内存分配比 native 进程复杂。

rk3288:/ # procrank
warning: could not create process interface for 24967
  PID       Vss      Rss      Pss      Uss     Swap    PSwap    USwap    ZSwap  cmdline
  444  1753980K  185776K   82769K   70984K      12K       0K       0K       0K  system_server
  939  1847220K  206384K   75608K   37820K      16K       0K       0K       0K  com.google.android.gms.persistent
 1123  1966504K  204908K   74534K   36636K      16K       0K       0K       0K  com.google.android.gms
 1169  1776436K  176736K   67141K   43504K      16K       0K       0K       0K  com.google.android.googlequicksearchbox:search
  569  1744108K  170132K   63116K   50736K      16K       0K       0K       0K  com.android.systemui
1.4 Android 中进程的堆内存

Android 进程中的 heap 空间完全由程序员控制,我们使用的 malloc、C++ new 和 java new 所申请的空间都是 heap 空间, C/C++申请的内存空间在 native heap 中,而j ava 申请的内存空间则在 dalvik heap 中。

1.5 android 程序的 OOM 异常

OOM 是因为 Android 系统对 dalvik 虚拟机的 heapsize 做了硬件要求,当 java 进程申请的 dalvik heap 超过阀值时,就会抛出 OOM 异常,这个阀值可能是 45M、24M 或者 128M,可以通过下列的命令查看这个值

$ getprop | grep dalvik.vm.heapgrowthlimit

所以程序发生 OOM 异常并不代表 RAM 不足,而是因为程序申请的 java heap 对象超过了 ,也就是说,在 RAM 充足的情况下,也可能发生 OOM 异常。

Google 这样设计的目的是为了让 Android 系统能同时让比较多的进程常驻内存,这样程序启动时就不用每次都重新加载到内存,能够给用户更快的响应。

1.5 大型应用程序如何绕过 dalvikvm heapsize 的限制

对于一些大型的应用程序(比如游戏),内存使用会比较多,很容易超超出 vm heapsiz e的限制,这时怎么保证程序不会因为 OOM 而崩溃呢?

(1)、创建子进程
     可以使用 android:process 标签
     这种做法会增加系统开销

(2)、使用 jni 在 native heap 上申请空间(推荐使用)
     native heap 的增长并不受 dalvik vm heapsize 的限制。
     只要RAM有剩余空间,程序员可以一直在native heap 上申请空间。

(3)、使用显存(操作系统预留 RAM 的一部分作为显存)
     使用 OpenGL textures 等 API,texture memory 不受dalvik vm heapsize限制。
     再比如 Android 中的 GraphicBufferAllocator 申请的内存就是显存。

猜你喜欢

转载自blog.csdn.net/qq_19923217/article/details/81098834