转载请标明出处:http://blog.csdn.net/xx326664162/article/details/52351047 文章出自:薛瑄的博客
你也可以查看我的其他同类文章,也会让你有一定的收货

我们都知道Android手机上是可以安装很多App的,每一个App至少是会有一个进程的。创建进程是件麻烦而且耗资源的事情,Android为了让App启动的时候能更快,会把那么暂时不使用的App的进程缓存起来,但是内存是有限的啊,总不能让所有的进程都放在内存里边吧,所以Android有一个淘汰机制,会根据App的运行状态设置一个进程的优先级(oom_adj),然后根据内存的紧张程度,把那些优先级低(oom_adj值大)的进程kill掉,以保证其他的进程能够有足够的内存使用。

注意:这个oom_adj值,是根据当前APP的运行状态(前台,后台等等)动态改变的。

进程

  1. Zygote进程
    这个是Android框架的主要进程,所有的App进程以及系统服务进程SystemServer都是由Zygote进程Fork出来的

  2. App的主进程
    每一个App的运行都是在一个独立的进程,进程的名字就是App的packagename,这些进程都是从Zygote进程Fork出来的,并受AMS(ActivityManagerService)管理

  3. App的辅助进程
    可以允许App有多个进程,在AndroidManifest.xml里边配置android:process属性,就可以开启多进程,这些进程名字都是packagename:name这种,以区分是属于哪个App,我一般称之为辅助进程。但这些进程也都跟主进程一样,也是从Zygote进程Fork出来的,并受AMS管理

  4. Native进程
    Android除了使用Java,还有NDK,可以使用C/C++去开发,然后这里也是可以Fork出进程的,我一般称之为Native进程,Native进程可以不受AMS管理,自由度很大,本文暂且不讲

如何查看App进程优先级

对于App进程,因为受AMS管理,都会有一个oom_adj的文件记录着oom_adj的值,但是对于Native进程,那AMS就管不着了。

//oom_adj的值就是进程的优先级,
//查看oom_adj值
cat /proc/${pid}/oom_adj

下面以查看微信的oom_adj为例,先通过ps | grep com.tencent.mm得到进程名包含“com.tencent.mm”的微信进程pid。ps命令使用详解可参考这里。

优先级

App进程的优先级是在com.android.server.am.ProcessList类里边定义的,这个类在Android的API里边是找不到的,要想看看里边的实现可以去Android SDK里边去找,位于${android-sdk-path}\sources\android-23\com\android\server\am\ProcessList.java

主要有这么几个优先级(oom_adj值):

  • UNKNOWN_ADJ = 16
    预留的最低级别,一般对于缓存的进程才有可能设置成这个级别

    Adjustment used in certain places where we don’t know it yet. (Generally this is something that is going to be cached, but we don’t know the exact value in the cached range to assign yet.)

  • CACHED_APP_MAX_ADJ = 15
    缓存进程,空进程,在内存不足的情况下就会优先被kill

    This is a process only hosting activities that are not visible, so it can be killed without any disruption.

  • CACHED_APP_MIN_ADJ = 9
    缓存进程,也就是空进程

  • SERVICE_B_ADJ = 8
    不活跃的进程

    The B list of SERVICE_ADJ – these are the old and decrepit services that aren’t as shiny and interesting as the ones in the A list.

  • PREVIOUS_APP_ADJ = 7
    切换进程

    This is the process of the previous application that the user was in. This process is kept above other things, because it is very common to switch back to the previous app. This is important both for recent task switch (toggling between the two top recent apps) as well as normal UI flow such as clicking on a URI in the e-mail app to view in the browser, and then pressing back to return to e-mail.

  • HOME_APP_ADJ = 6
    与Home交互的进程

    This is a process holding the home application – we want to try avoiding killing it, even if it would normally be in the background, because the user interacts with it so much.

  • SERVICE_ADJ = 5
    有Service的进程

    This is a process holding an application service – killing it will not have much of an impact as far as the user is concerned.

  • HEAVY_WEIGHT_APP_ADJ = 4
    高权重进程

    This is a process with a heavy-weight application. It is in the background, but we want to try to avoid killing it. Value set in system/rootdir/init.rc on startup.

  • BACKUP_APP_ADJ = 3
    正在备份的进程

    This is a process currently hosting a backup operation. Killing it is not entirely fatal but is generally a bad idea.

  • PERCEPTIBLE_APP_ADJ = 2
    可感知的进程,比如那种播放音乐

    This is a process only hosting components that are perceptible to the user, and we really want to avoid killing them, but they are not immediately visible. An example is background music playback.

  • VISIBLE_APP_ADJ = 1
    可见进程

    This is a process only hosting activities that are visible to the user, so we’d prefer they don’t disappear.

  • FOREGROUND_APP_ADJ = 0
    前台进程
    This is the process running the current foreground app. We’d really rather not kill it!

  • PERSISTENT_SERVICE_ADJ = -11
    重要进程

    This is a process that the system or a persistent process has bound to, and indicated it is important.

  • PERSISTENT_PROC_ADJ = -12
    核心进程

    This is a system persistent process, such as telephony. Definitely don’t want to kill it, but doing so is not completely fatal.

  • SYSTEM_ADJ = -16
    系统进程

    The system process runs at the default adjustment.

  • NATIVE_ADJ = -17
    系统起的Native进程

    Special code for native processes that are not being managed by the system (so don’t have an oom adj assigned by the system).

在Android-18及以下空进程不叫CACHED_APP_MIN_ADJ ,叫HIDDEN_APP_MIN_ADJ,有这么点不一样,但是值都一样。

lowmemorykiller 机制

这个机制是在goldfish层面实现的,如果要想具体了解是怎么选择杀进程的话,需要去看Android drivers下的lowmemorykiller.c的代码。

编译过goldfish的人,应该知道它其实就是Linux kernel。因为Android是基于Linux的操作系统嘛,kernel其实也是跟着Linux kernel走的,只不过在里边需要开发(或者精简)一些专门针对Android的东西,lowmemorykiller 就是其中的一部分,是个驱动。至于为啥会被放在drivers/staging目录下,可以参考下这篇文章《小议Linux staging tree》

有这么几个关键点:

  1. 向系统注册lowmem_shrinker回调,当系统空闲内存不足时调用,去杀进程

  2. 把空闲内存低于多少,就去杀那个级别的进程,我称之为策略

  3. 杀的策略由application层根据内存状况指定,写入文件传递给驱动

  4. 根据策略会计算出min_score_adj

  5. 每个App进程都有oom_adj值,根据oom_adj值计算出oom_score_adj(得分值),oom_adj越大,oom_score_adj越高,高于min_score_adj的被列入死亡名单

  6. 在死亡名单里面选一个占内存最大的进程kill掉

所以当内存不足的时候,进程优先级低的(oom_adj越大的),占内存大的App进程将会被优先kill掉。

至于这个策略嘛,各个ROM可能不一致的,根据内存的大小,系统的严格程度来制定,但都只能分6个级别。

查看传给lowmemorykiller驱动的策略文件:

  • minfree:列举6个内存阀值。
    比如:32768,61440,73728,129024,147456,184320

  • adj:列举6个oom_adj的级别。
    比如:0,1,2,3,9,15

这两个值相互对应,空闲内存低于多少的时候就kill那个级别的进程。

当然有些ROM也会把这个参数定义在init.rc里边,开机后再写入minfree和adj文件,传递给驱动

trimApplications机制

仅仅只有低内存的情况下才去kill进程吗?很明显不是,对于App的运行是有很多状况的,比如Crash、App退出、系统清理、卸载。

trimApplications是一个方法,定义在ActivityManagerService里边,Android API里边也是没有这个类的,得去SDK里边找,位于${android-sdk-path}\sources\android-23\com\android\server\am\ActivityManagerService.java

这个机制大概也有几个关键点:

  1. package已被卸载的无用进程会被Kill
  2. persistent的App会被优先照顾,进程优先级设置为
    PERSISTENT_PROC_ADJ=-12
  3. Activity仅在主进程跑的App会被认为是高权重进程,HEAVY_WEIGHT_APP_ADJ=4
  4. 只有前台进程才是FOREGROUND_APP_ADJ=0,前台进程不会被杀
  5. 每当Activity、Service等生命周期发生变化的时候都会引起进程的oo_adj的调整
  6. 进程里边没有任何的Activity的存在优先被杀
  7. 空进程最容易被杀

如何提高后台App进程的优先级

其实Android框架的思想是很好的,对于空的进程,没事干的进程直接kill掉,对于用户体验来讲是不会有影响的,但是往往我们的App都会有推送这个功能,恰巧GCM(Google Cloud Messaging)在国内又不能用,所以很多情况下我们也会希望App在后台的时候也尽量不要被杀。

可以考虑把后台App进程的优先级提高,下面有几个方法:

  • AndroidManifest.xml中配置persistent属性
<application android:name="App"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
  • 重载back按键事件,让activity在后台运行,不要Destory
  • 开Service,并设置前台运行方式
  • 与NotificationManager交互,让进程变成可感知进程
  • 发送/接收广播,别让自己变成空进程

很明显这会消耗更多的电量,也有点流氓,有些需求也许本就不该做。

参考:

Android平台App进程优先级

微信Android客户端后台保活经验分享

Android平台App进程优先级相关推荐

  1. mac上配置cordova开发Android平台APP环境

    cordova上有说明文档,如何开始一个APP: cordova中文文档 在配置环境这块没有详细说明,只是简单介绍了一下步骤 在cordova中文文档中我们看到需要安装以下4个东西.(Android ...

  2. 设置IOS平台和Android平台APP的URL Scheme

    URL Scheme的作用 APP可以向手机操作系统注册一个 URL scheme,该 scheme 用于从浏览器或其他应用中启动本应用. 设置IOS平台的URL Scheme IOS应用在info. ...

  3. android的反调试方法,Android平台融合多特征的APP反调试方法与流程

    本发明涉及Android平台融合多特征的APP反调试方法,属于计算机与信息科学技术领域. 背景技术: 应用程序本身并不具备反调试的功能,但是动态调试是动态分析应用逻辑.动态脱壳等攻击方式所采取的必要手 ...

  4. 计算机毕业设计基于Android平台的公交线路查询系统app

    基于Android平台的公交线路查询就是一个可以帮助用户便捷的浏览公交信息的公交线路查询的优秀app,手机联网或者通过USB连接电脑下载即可,在手机上安装完成,直接就可以使用,使用者可以通过公交线路查 ...

  5. 物联网平台搭建的全过程介绍(五)——基于阿里云物联网平台的Android聊天app源码

    本例程Android源码请点此处免费下载 物联网平台搭建的全过程介绍(四)两台设备之间通过云数据流转实现远程通信之Android studio例程中介绍了两台Android设备通过物联网平台进行通信的 ...

  6. 超级应用 - 免费应用内测托管平台|APP应用分发平台|iOS应用分发|Android应用分发|免费应用内测托管平台 源码下载

    网站标题:超级应用 - 免费应用内测托管平台|APP应用分发平台|iOS应用分发|Android应用分发|免费应用内测托管平台源码下载 网站关键词:超级应用(www.awwjd.com) 为您提供测试 ...

  7. Java实现旅游app_基于安卓Android平台的旅游系统APP的设计(Eclipse,MySQL)

    基于安卓Android平台的旅游系统APP的设计(Eclipse,MySQL)(任务书,开题报告,论文15700字,程序代码) 摘  要 随着手机使用的普及,人们获取与保存信息的方式已经发生了激动人心 ...

  8. android外卖实验报告,基于Android平台的外卖app设计与实现.doc

    摘要:二十一世纪以来,在计算机及相关技术的高速迅猛发展的背景下,手机的使用逐渐普及并成为生活中不可或缺的一部分.当第一台智能手机问世以后,人类社会中信息的传递开始有了翻天覆地的变化.为了满足目前信息时 ...

  9. 基于Android平台的公交线路查询系统app

    基于Android平台的公交线路查询就是一个可以帮助用户便捷的浏览公交信息的公交线路查询的优秀app,手机联网或者通过USB连接电脑下载即可,在手机上安装完成,直接就可以使用,使用者可以通过公交线路查 ...

最新文章

  1. 用计算机弹奏lemon乐谱,原神乐谱lemon怎么弹 lemon乐谱弹奏方法教学
  2. 启用新域名:ju690.com --聚了就灵的谐音
  3. Lazy Load, 延迟加载图片的 jQuery 插件
  4. 百练OJ:2742:统计字符数
  5. [网络安全自学篇] 二十八.文件上传入门及防御原理(一)
  6. java中获取文件路径的几种方式
  7. TODO-MVP-Loaders源码体验
  8. CoreOS 收购 Quay.io 发布私有 Docker 仓库
  9. 操作员界面图形设计的基本原则
  10. php 操作xls,php中使用PHPExcel操作excel(xls)文件
  11. ★古今中外著名14大悖论
  12. 【Julia】 解决安装包下载慢的问题
  13. 跟我学Python图像处理丨带你掌握傅里叶变换原理及实现
  14. python爬取bilibili数据_用 Python 抓取 bilibili 弹幕并分析!
  15. 深度学习 VS 传统的机器学习
  16. 阿里云验证码与通知短信
  17. 【李航统计学习方法】感知机模型
  18. ICM20602六轴传感器-IIC通信模式
  19. 计算机二级关于ppt的题目,全国计算机二级题库Ppt题目考点.doc
  20. Android开发本地及网络Mp3音乐播放器(五)实现专辑封面图片

热门文章

  1. WIN10管理员权限设置、更改用户名被“拒绝访问”
  2. Mathorcup数学建模竞赛第六届-【妈妈杯】A题:淡水养殖池塘水华发生及池水自净化研究(附一等奖获奖论文和matlab代码)
  3. android锁屏界面快捷键,Funtouch新特性 锁屏快捷键可以自定义
  4. .podSpec文件相关知识整理
  5. matlab背景色为白色
  6. 电磁兼容工程(Electromagnetic compatibility engineering Herry Ott )读书笔记--章12 数字电路的辐射
  7. 水利水电工程有学计算机吗,为什么说千万别学水利水电工程 原因有哪些
  8. Authentication failed for 解决办法
  9. hive和presto下标准时间格式和时间戳的转化
  10. [树莓派 PICO(基于MicroPython)]基础教程02-按键测试、按键控制外设LED开关