Android开发中,令人头疼的保活问题始终缠绕每一个开发者。如何保证自己的进程不被系统回收呢?首当其冲应该是保证自己进程的优先级。

Android系统在运行时,如果遭遇到内存过低,为保证系统稳定与流畅,会回收一部分不常用的进程(当然很多三方rom如miui会在电量过低也会回收)。这个回收过程当然不是随意回收,系统需要有一个判断进程优先级的指标,帮助系统判断哪些资源是优先级高需要保留,哪些资源优先级比较低需要释放该资源。

ADJ就是系统杀死进程的重要指标

本文从linux\Android进程优先级:adj分数,浅析一下如何查看adj以及各个adj分数背后所代表的含义。
1.ADJ 如何查看

利用adb shell

1.ps | grep 包名  //查看当前app的进程号2.cat /proc/进程号/oom_adj  //查看当前进程的adj值(早期android和linux使用,现已废弃,但仍然有效)3.cat /proc/进程号/oom_score_adj    //这个是新版本的查看adj的命令,adj有效值为-1000~1000

2.ADJ的值的各种含义
ADJ级别 取值 含义

NATIVE_ADJ              -1000   native进程
SYSTEM_ADJ              -900    仅指system_server进程
PERSISTENT_PROC_ADJ     -800    系统persistent进程
PERSISTENT_SERVICE_ADJ  -700    关联着系统或persistent进程
FOREGROUND_APP_ADJ      0       前台进程
VISIBLE_APP_ADJ         100     可见进程
PERCEPTIBLE_APP_ADJ     200     可感知进程,比如后台音乐播放
BACKUP_APP_ADJ          300     备份进程
HEAVY_WEIGHT_APP_ADJ    400     重量级进程
SERVICE_ADJ             500     服务进程(A list中的service)
HOME_APP_ADJ            600     Home进程
PREVIOUS_APP_ADJ        700     上一个进程
SERVICE_B_ADJ           800     B List中的Service
CACHED_APP_MIN_ADJ      900     不可见进程的adj最小值
CACHED_APP_MAX_ADJ      906     不可见进程的adj最大值

3.ADJ触发顺序

ADJ是一种算法,用于系统判断进程优先级以触发Linux的LMK(LowMemoryKill)机制。一般触发时机(Linux下)是在系统低内存时,为了维护正在运行的进程,杀掉优先级比较低(adj值比较高)的其他进程。

在Android中这一机制有所改动。在ActivityManagerService里有具体的计算Adj值的源码。

进程刚启动时ADJ等于INVALID_ADJ,当执行完attachApplication(),该该进程的curAdj和setAdj不相等,则会触发执行setOomAdj()将该进程的节点/proc/pid/oom_score_adj写入oomadj值。下图参数为Android原生阈值,当系统剩余空闲内存低于某阈值(比如147MB),则从ADJ大于或等于相应阈值(比如900)的进程中,选择ADJ值最大的进程,如果存在多个ADJ相同的进程,则选择内存最大的进程。 如下是64位机器,LMK默认阈值图:

----------ADJ----------------Memory Left------------
FOREGROUND_APP_ADJ(0)          73MB
VISIBLE_APP_ADJ(100)           92MB
PERCEPTIBLE_APP_ADJ(200)       110MB
BACKUP_APP_ADJ(300)            129MB
CACHED_APP_MIN_ADJ(900)        221MB
CACHED_APP_MAX_ADJ(906)        332MB

4.高级进程 ADJ<0的进程

1.NATIVE_ADJ(-1000):是由init进程fork出来的Native进程,并不受system管控;

2.SYSTEM_ADJ(-900):是指system_server进程;

3.PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系统(即带有FLAG_SYSTEM标记)进程,persistent进程一般情况并不会被杀,即便被杀或者发生Crash系统会立即重新拉起该进程。

4.PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式启动的进程,或者是由system_server或者persistent进程所绑定(并且带有BIND_ABOVE_CLIENT或者BIND_IMPORTANT)的服务进程
5.总结

Android进程优先级ADJ的每一个ADJ级别往往都有多种场景,使用adjType完美地区分相同ADJ下的不同场景; 不同ADJ进程所对应的schedGroup不同,从而分配的CPU资源也不同,schedGroup大体分为TOP(T)、前台(F)、后台(B); ADJ跟AMS中的procState有着紧密的联系。

1.adj:通过调整oom_score_adj来影响进程寿命(Lowmemorykiller杀进程策略);

2.schedGroup:影响进程的CPU资源调度与分配;

3.procState:从进程所包含的四大组件运行状态来评估进程状态,影响framework的内存控制策略。比如控制缓存进程和空进程个数上限依赖于procState,再比如控制APP执行handleLowMemory()的触发时机等。
为了说明整体关系,以ADJ为中心来讲解跟adjType,schedGroup,procState的对应关系,下面以一幅图来诠释整个ADJ算法的精髓,几乎涵盖了ADJ算法调整的绝大多数场景。
6.最后,开发时应注意:

1.UI进程与Service进程一定要分离,因为对于包含activity的service进程,一旦进入后台就成为”cch-started-ui-services”类型的cache进程(ADJ>=900),随时可能会被系统回收;而分离后的Service进程服务属于SERVICE_ADJ(500),被杀的可能性相对较小。尤其是系统允许自启动的服务进程必须做UI分离,避免消耗系统较大内存。
只有真正需要用户可感知的应用,才调用startForegroundService()方法来启动前台服务,此时ADJ=PERCEPTIBLE_APP_ADJ(200),常驻内存,并且会在通知栏常驻通知提醒用户,比如音乐播放,地图导航。切勿为了常驻而滥用前台服务,这会严重影响用户体验。

2.进程中的Service工作完成后,务必主动调用stopService或stopSelf来停止服务,避免占据内存,浪费系统资源;

3.不要长时间绑定其他进程的service或者provider,每次使用完成后应立刻释放,避免其他进程常驻于内存;

4.APP应该实现接口onTrimMemory()和onLowMemory(),根据TrimLevel适当地将非必须内存在回调方法中加以释放。当系统内存紧张时会回调该接口,减少系统卡顿与杀进程频次。

5.减少在保活上花心思,更应该在优化内存上下功夫,因为在相同ADJ级别的情况下,系统会选择优先杀内存占用的进程。

原文:https://blog.csdn.net/zhangbijun1230/article/details/81347749
链接:https://www.jianshu.com/p/baef5c943eb4

Android App 保活之 ADJ 算法相关推荐

  1. Android 系统(248)---解读Android进程优先级ADJ算法

    本文基于原生Android P源码来解读进程优先级原理,基于篇幅考虑会精炼部分代码 一.概述 1.1 进程 Android框架对进程创建与管理进行了封装,对于APP开发者只需知道Android四大组件 ...

  2. Android进程保活(如何尽可能避免APP被杀死)

    #.Android进程的优先级 Android系统中进程有不同的优先级,在系统需要优化和回收资源时,会先杀死优先级低的进程.所以要保活一个进程,就要想办法尽可能去提升它的优先级. ##1.前台进程 - ...

  3. Android进程保活(黑白手段让APP活下去)

    凡是做过几年Android开发的,都不能不面对进程保活这一问题.特别是这两年,面对谷歌,国内定制ROM,安全软件等多方围剿的情况下,app在后台保活的难度越来越大,可以说包括QQ.微信在内的所有app ...

  4. 关于Android安卓APP保活 - 安卓消息推送详解 - 安卓端外推送离线推送

    转自:http://zhangtielei.com/posts/blog-android-push.html 说Android端外推送比较烦,实际有两层意思:首先是说实现上比较麻烦,至今业界也没有找到 ...

  5. android 音乐app 保活,aggregationProject聚合项目

    aggregationProject聚合项目 介绍 Android聚合项目,包含自定义分享模块.自定义音频播放模块.okhttp的封装模块.加载图片工具模块.app保活模块.自定义视频模块等 软件架构 ...

  6. Android之APP保活

    前言 强烈建议不要这么做,不仅仅从用户角度考虑,它只会滋生更多的流氓应用,拖垮Android 平台的流畅性(假如你手机里装了支付宝.淘宝.天猫.UC等阿里系的app,那么你打开任意一个阿里系的app后 ...

  7. Android 自用 App保活——音乐播放保活适配8.0 (贼好用)

    又是好久没有积累东西了.惭愧,惭愧...手动哭泣.闲话说到这里,下面我介绍一种新的 App 保活方式哈,目前用小米家族手机 涵盖 Android 5.0 到 Android 8.1家族的测试.结论是, ...

  8. 从framework角度看app保活问题

    问题背景 最近在群里看到群友在讨论app保活的问题,回想之前做应用(运动类)开发时也遇到过类似的需求,于是便又来了兴趣,果断加入其中,和群友展开了激烈的讨论 不少群友的想法和我当初的想法一样,这特么保 ...

  9. Android进程保活方案

    自己曾经也在这个问题上伤过脑经,前几日刚好有一个北京的哥们在QQ说在做IM类的项目,问我进程保活如何处理比较恰当,决定去总结一下,网上搜索一下进程常驻的方案好多好多,但是很多的方案都是不靠谱的或者不是 ...

最新文章

  1. js根据经纬度取随机附近经纬度
  2. 3.playbook基础
  3. 清除memcached缓存数据的方式
  4. fastdfs安装_FastDFS 安装部署文档
  5. 解决python中文乱码的方法
  6. 怎么成为日上会员直邮_18个日上直邮问题汇总,可以参考一下哦
  7. struct sockaddr_nl 结构体 由来、含义以及使用——获取Linux路由表
  8. SQL Server 索引结构及其使用(三)(转)
  9. python装饰器怎么调用_Python学习22-外部程序的调用装饰器
  10. 记事本编程开发以及IDEA编程开发
  11. matlab weibpdf函数,MATLAB常用函数
  12. 前端工程师的摸鱼日常(15)
  13. Esxi通过U盘启动
  14. FastStone注册码
  15. 中国企业说专列国庆开行 北京地铁一号线披上中国红迎国庆
  16. Windows平台mantis安装
  17. python猜单词游戏_python实现猜单词游戏
  18. 诸葛越:关于算法工程师职业发展的思考
  19. C#高性能低GC 非托管动态扩容数组
  20. 用python爬荣耀皮肤图片(爬虫最基础题,python爬虫教程,超详细+完整代码)

热门文章

  1. php获取公众号微信用户信息
  2. 观察者模式(结合C#,Unity)
  3. 程序员面试,面试官更注重代码量、项目经验还是操作系统、数据结构这种基础课程?...
  4. 打造流畅九宫格抽奖活动
  5. 戴尔sc系列存储阵列柜服务器,Dell存储Compellent SC4020
  6. android os感染病毒,安卓系统能感染win系统病毒吗?
  7. JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快!
  8. VS2019 error C2855: 命令行选项“/source-charset”与预编译头不一致(Charsets inconsistent with precompiled heade)
  9. 发现个下载Sailfish OS源码的地方
  10. Warning: Data truncated for column at row 1