文章目录
1. 进程的优先级
https://developer.android.google.cn/guide/components/activities/process-lifecycle?hl=zh-cn
1.1. 前台进程
指正在与用户进行交互的应用进程,该进程数量较少, 是最高优先级进程, 系统一般不会终止该进程。
- 进程中包含处于前台的正与用户交互(onResume状态)的Activity。
- 进程中包含与前台 Activity 绑定的 Service。
- 进程中包含调用了
startForeground()
方法的 Service。 - 进程中包含正在执行
onCreate()
、onStart()
或onDestroy()
方法的 Service。 - 进程中包含正在执行
onReceive()
方法的 BroadcastReceiver。
1.2. 可视进程
能被用户看到,但不能根据根据用户的动作做出相应的反馈。
- 进程中包含可见但不处于前台进程(onPause状态)的 Activity(弹出对话窗时 Activity 处于可见状态,但并不处于前台进程中)。
- 该进程有一个与可见或前台的 Activity 绑定数据的 Service。
- 系统正在使用其托管的服务实现用户知晓的特定功能,例如动态壁纸、输入法服务等。
1.3. 服务进程
没有可见界面仍在不断的执行任务的进程,除非在可视进程和前台进程紧缺资源才会被终止。可以被认为是前台进程,但是运行了很长时间(例如 30 分钟或更长时间)的服务的重要性可能会降位。
- 已使用
startService()
方法启动的 Service。 - 包含除前台进程和可视进程的 Service 外的 Service 的进程。
1.4. 后台进程
进程中的 Activity 不可见且进程中没有任何启动的 Service,这些进程都是后台进程。通常系统中有大量的后台进程,终止后台进程不会影响用户体验,随时为优先级更高的进程腾出资源而被终止,优先回收长时间没用使用过的进程。
这些后台进程保存在伪 LRU 列表中,列表中的最后一个进程是为了回收内存而终止的第一个进程。
1.5. 空进程
为提高整体系统性能,系统会保存已经完成生命周期的应用程序 , 存在内存中,为下次的启动更加迅速而设计。通常会被定期地终止。当一个进程被杀掉,但进程保留,变成空进程。
2. LowmemoryKiller
LowmemoryKiller(简称lmk)管理所有进程,根据一定策略来杀掉某个进程并释放占用的内存,保证系统的正常运行。
2.1. 原理
所有应用进程从 Zygote 孵化出来的进程都会记录在 ActivityManagerService.mLruProcesses
的列表中,由 ActivityManagerService 进行统一管理,时时更新进程的状态,根据状态计算出进程对应的 OomAdj 值,这个值会传递到 kernel 中去,kernel 有个低内存回收机制,在内存达到一定阈值(不同手机不一样)时会触发清理 OomAdj 值高的进程,从而释放内存空间。
adb shell dumpsys meminfo // 查看每个进程内存使用状况
adb shell su // 启用su权限
cat /sys/module/lowmemorykiller/parameters/minfree // 查看minfree
// 第一个值:18432(72MB)达到这个值时候,前台进程就会被杀死
// 第二个值:23040(90MB)达到这个值的时候,可见进程就会被杀死
// 第三个值:27648(108MB)达到这个值的时候,服务进程会被杀死
// 第四个值:32256(126MB)达到这个值的时候,后台进程会被杀死
// 第五个值:55296(216MB)达到这个值的时候,ContentProvider会被杀死
// 第六个值:80640(315MB)达到这个值的时候,空进程会被杀死
cat /sys/module/lowmemorykiller/parameters/adj // 查看手机adj
cat /proc/<pid>/oom_adj // 查看进程adj
cat /proc/<pid>/oom_score_adj // 查看进程adj
2.2. 划分标准
oom_adj 划分为16级,从-17到16之间,越大优先级越低。
ADJ 级别 | 取值 | 解释 |
---|---|---|
UNKNOWN_ADJ | 16 | 一般指将要会缓存进程,无法获取确定值 |
CACHED_APP_MAX_ADJ | 15 | 不可见进程的 adj 最大值 |
CACHED_APP_MIN_ADJ | 9 | 不可见进程的 adj 最小值 |
SERVICE_B_ADJ | 8 | B List 中的 Service(较老的、使用可能性更小) |
PREVIOUS_APP_ADJ | 7 | 上一个 App 的进程 (往往通过按返回键) |
HOME_APP_ADJ | 6 | Home 进程 |
SERVICE_ADJ | 5 | 服务进程 (Service process) |
HEAVY_WEIGHT_APP_ADJ | 4 | 后台的重量级进程,system/rootdir/init.rc 文件中设置 |
BACKUP_APP_ADJ | 3 | 备份进程 |
PERCEPTIBLE_APP_ADJ | 2 | 可感知进程,比如后台音乐播放 |
VISIBLE_APP_ADJ | 1 | 可见进程 (Visible process) |
FOREGROUND_APP_ADJ | 0 | 前台进程(Foreground process) |
PERSISTENT_SERVICE_ADJ | -11 | 关联着系统或 persistent 进程 |
PERSISTENT_PROC_ADJ | -12 | 系统 persistent 进程,比如 telephony |
SYSTEM_ADJ | -16 | 系统进程 |
NATIVE_ADJ | -17 | native 进程(不被系统管理) |
3. 进程保活
3.1. Activity提权
监控手机锁屏解锁事件,在屏幕锁屏时启动1个像素透明的 Activity,在用户解锁时将 Activity 销毁,从而达到提高进程优先级的作用。
创建Activity
创建一个1像素的 Activity,例如名称为 KeepActivity
Window window = getWindow();
window.setGravity(Gravity.START | Gravity.TOP);
WindowManager.LayoutParams attributes = window.ge