Android 内存管理原理

在Android开发中我们常常遇到app在后台长期不使用时被系统自动回收掉,Android系统是怎么实现这个功能的呢。我们不讨论如何让app保活的方法,主要来说说系统实现这一机制的原理

1、描述进程的重要程度——oom_adj

在Android系统中使用oom_adj值来描述一个进程的重要程度,它是AMS的Process类型中的一个变量,oom_adj值越小,表示进程越重要,越不容易被杀掉。以下是AMS中定义的一些oom_adj值

    static final int EMPTY_APP_ADJ;

    static final int HIDDEN_APP_MAX_ADJ;

    static final int HIDDEN_APP_MIN_ADJ;

    static final int HOME_APP_ADJ;

    static final int BACKUP_APP_ADJ;

    static final int SECONDARY_SERVER_ADJ;

    static final int HEAVY_WEIGHT_APP_ADJ;

    static final int PERCEPTIBLE_APP_ADJ;

    static final int VISIBLE_APP_ADJ;

    static final int FOREGROUND_APP_ADJ;

    static final int CORE_SERVER_ADJ = -12;

    static final int SYSTEM_ADJ = -16; 

可以看到一些运行核心服务的进程的oom_adj为-12(CORE_SERVER_ADJ),这类进程基本不会被杀死。其他未赋值的都在static块中进行了初始化,是通过system/rootdir/init.rc进行配置的:

# Define the oom_adj values for the classes of processes that can be

# killed by the kernel.  These are used in ActivityManagerService.

   setprop ro.FOREGROUND_APP_ADJ 0

   setprop ro.VISIBLE_APP_ADJ 1

   setprop ro.SECONDARY_SERVER_ADJ 2

   setprop ro.HIDDEN_APP_MIN_ADJ 7

   setprop ro.CONTENT_PROVIDER_ADJ 14

   setprop ro.EMPTY_APP_ADJ 15

 

# Define the memory thresholds at which the above process classes will

# be killed.  These numbers are in pages (4k).

   setprop ro.FOREGROUND_APP_MEM 1536

   setprop ro.VISIBLE_APP_MEM 2048

   setprop ro.SECONDARY_SERVER_MEM 4096

   setprop ro.HIDDEN_APP_MEM 5120

   setprop ro.CONTENT_PROVIDER_MEM 5632

   setprop ro.EMPTY_APP_MEM 6144

可以看到前台进程的oom_adj值为0,这类进程时我们正在交互的进程,基本也不会被杀掉;空进程对应的值是15,当系统内存不足是最新杀掉的就是这类进程(这类进程一般指的是所有的activity都destory掉了,并且没有service在运行)。adj值下面描述的是各种内存阀值。比如当系统剩余内存小于6144 * 4kb(ro.EMPTY_APP_MEM)是emty 进程就会被回收掉。这些值对与每个手机厂商生产的手机都是不一样的。以下是oom_adj值对应的内存阀值

0 1536 
1 2048 
2 4096 
7 5120 
14 5632 
15 6144

如上所说,当系统内存小于6144 * 4kb时empty进程将会被回收掉,而empty进程的oom_adj值为15。在Activity、service、contentProvider、Broadcast Android四大组件的状态的变化都会导致AMS更新对应进程oom_adj值,所以前台进程比后台进程更不容易杀掉,带有service的后台进程比没有service的进程更不容易被杀掉

2、LMK

LMK的全称是low memory killer,它是内核的一个模块。它里面保存了各个进程的pid以及对应的oom_adj,每次AMS调用updateOOmAdj函数更新进程的oom_adj时都会通知LMK模块。
LMK通过linux的shrinker模块来监听系统的内存变化,当系统的剩余内存达到某个阀值时就会杀掉oom_adj值大于这个阀值对应的oom_adj的进程。它会优先杀掉内存占用多的进程,如果杀掉这些进程内存回到了正常值将不会继续杀进程。所以让app不要占用大量的内存也可以起到保活的作用

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容