Android进程
本文知识点包括:如何使用adb查看进程信息&进程划分&内存阈(yu四声)值
进程是一个具有独立功能的程序关于某个数据集合的一次运行活动,线程是CPU执行的最小单元,进程包含线程.
如何查看进程解基本信息
对于任何一个进程,我们都可以通过adb shell ps|grep <package_name>的方式来查看它的基本信息
值 | 解释 |
---|---|
u0_a16 | USER 进程当前用户 |
3881 | 进程ID |
1223 | 进程的父进程ID |
873024 | 进程的虚拟内存大小 |
37108 | 实际驻留”在内存中”的内存大小 |
com.wangjing.processlive | 进程名 |
进程划分
Android中的进程跟封建社会一样,分了三流九等,Android系统把进程的划为了如下几种(重要性从高到低),网上多位大神都详细总结过(备注:严格来说是划分了6种)。
前台进程(Foreground process)
场景:
- 某个进程持有一个正在与用户交互的Activity并且该Activity正处于resume的状态。
- 某个进程持有一个Service,并且该Service与用户正在交互的Activity绑定。
- 某个进程持有一个Service,并且该Service调用startForeground()方法使之位于前台运行。
- 某个进程持有一个Service,并且该Service正在执行它的某个生命周期回调方法,比如onCreate()、 onStart()或onDestroy()。
- 某个进程持有一个BroadcastReceiver,并且该BroadcastReceiver正在执行其onReceive()方法。
用户正在使用的程序,一般系统是不会杀死前台进程的,除非用户强制停止应用或者系统内存不足等极端情况会杀死。
可见进程(Visible process)
场景:
- 拥有不在前台、但仍对用户可见的 Activity(已调用 onPause())。
- 拥有绑定到可见(或前台)Activity 的 Service
用户正在使用,看得到,但是摸不着,没有覆盖到整个屏幕,只有屏幕的一部分可见进程不包含任何前台组件,一般系统也是不会杀死可见进程的,除非要在资源吃紧的情况下,要保持某个或多个前台进程存活
服务进程(Service process)
场景
- 某个进程中运行着一个Service且该Service是通过startService()启动的,与用户看见的界面没有直接关联。
在内存不足以维持所有前台进程和可见进程同时运行的情况下,服务进程会被杀死
后台进程(Background process)
场景:
- 在用户按了"back"或者"home"后,程序本身看不到了,但是其实还在运行的程序,比如Activity调用了onPause方法
系统可能随时终止它们,回收内存
空进程(Empty process)
场景:
- 某个进程不包含任何活跃的组件时该进程就会被置为空进程,完全没用,杀了它只有好处没坏处,第一个干它!
内存阈值
上面是进程的分类,进程是怎么被杀的呢?系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app, 这套杀进程回收内存的机制就叫 Low Memory Killer。那这个不足怎么来规定呢,那就是内存阈值,我们可以使用cat /sys/module/lowmemorykiller/parameters/minfree来查看某个手机的内存阈值。
注意这些数字的单位是page. 1 page = 4 kb.上面的六个数字对应的就是(MB): 72,90,108,126,144,180,这些数字也就是对应的内存阀值,内存阈值在不同的手机上不一样,一旦低于该值,Android便开始按顺序关闭进程. 因此Android开始结束优先级最低的空进程,即当可用内存小于180MB(46080*4/1024)。
读到这里,你或许有一个疑问,假设现在内存不足,空进程都被杀光了,现在要杀后台进程,但是手机中后台进程很多,难道要一次性全部都清理掉?当然不是的,进程是有它的优先级的,这个优先级通过进程的adj值来反映,它是linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来决定是否进行回收,adj值定义在com.android.server.am.ProcessList类中,这个类路径是${android-sdk-path}\sources\android-23\com\android\server\am\ProcessList.java。oom_adj的值越小,进程的优先级越高,普通进程oom_adj值是大于等于0的,而系统进程oom_adj的值是小于0的,我们可以通过cat /proc/进程id/oom_adj可以看到当前进程的adj值。
看到adj值是0,0就代表这个进程是属于前台进程,我们按下Back键,将应用至于后台,再次查看:
adj值变成了8,8代表这个进程是属于不活跃的进程,你可以尝试其他情况下,oom_adj值是多少,但是每个手机的厂商可能不一样,oom_adj值主要有这么几个,可以参考一下。
adj级别 | 值 | 解释 |
---|---|---|
UNKNOWN_ADJ | 16 | 预留的最低级别,一般对于缓存的进程才有可能设置成这个级别 |
CACHED_APP_MAX_ADJ | 15 | 缓存进程,空进程,在内存不足的情况下就会优先被kill |
CACHED_APP_MIN_ADJ | 9 | 缓存进程,也就是空进程 |
SERVICE_B_ADJ | 8 | 不活跃的进程 |
PREVIOUS_APP_ADJ | 7 | 切换进程 |
HOME_APP_ADJ | 6 | 与Home交互的进程 |
SERVICE_ADJ | 5 | 有Service的进程 |
HEAVY_WEIGHT_APP_ADJ | 4 | 高权重进程 |
BACKUP_APP_ADJ | 3 | 正在备份的进程 |
PERCEPTIBLE_APP_ADJ | 2 | 可感知的进程,比如那种播放音乐 |
VISIBLE_APP_ADJ | 1 | 可见进程 |
FOREGROUND_APP_ADJ | 0 | 前台进程 |
PERSISTENT_SERVICE_ADJ | -11 | 重要进程 |
PERSISTENT_PROC_ADJ | -12 | 核心进程 |
SYSTEM_ADJ | -16 | 系统进程 |
NATIVE_ADJ | -17 | 系统起的Native进程 |
备注:(上表的数字可能在不同系统会有一定的出入)
根据上面的adj值,其实系统在进程回收跟内存回收类似也是有一套严格的策略,可以自己去了解,大概是这个样子的,oom_adj越大,占用物理内存越多会被最先kill掉,OK,那么现在对于进程如何保活这个问题就转化成,如何降低oom_adj的值,以及如何使得我们应用占的内存最少。
by .k
关注"编程v",每一天涨一点
STAY HUNGRY & STAY FOOLISH