文章目录

  • 前言
  • 一、原理篇
    • 1. 什么是Android LMK
    • 2. OOM
    • 3. oom_adj 的值是如何赋予的
    • 4. LMK的工作机制
    • 5.Android进程优先级
      • 5.1 Android进程的优先级
      • 5.2. Android进程的回收策略
      • 5.3 保活的方法
  • 二、方法篇
  • 三、总结

前言

上文主要介绍了Andorid内存的管理机制,本文对其中的LMK机制进行深入扩展总结。

我们知道出现Crash应用闪退和崩溃一般有三个原因:ANR(程序无响应)、Exception(异常)、LMK(低内存杀死机制)。本文重点介绍LMK机制。

目的: 通过阅读本文,可以了解Android LMK机制,探究进程保活的方案和程序异常处理的方法。

一、原理篇

1. 什么是Android LMK

KMK,(Low Memory Killer )低内存杀死机制。由于Android应用的沙箱机制,每个应用程序都运行在一个独立的进程中,各自拥有独立的Dalvik虚拟机实例,系统默认分配给虚拟机的内存是有限度的,当系统内存太低依然会触发LMK机制,即出现闪退、崩溃现象。

不同厂商不同,如:华为mate7,192M ;小米4,128M ;红米,128M 。而在,Android4.0以后,可以通过在application节点中设置属性android:largeHeap=”true”来设置最大可分配多少内存空间就可以突破一定限制。

2. OOM

OOM(OutOfMemoryError)内存溢出错误 。导致OOM的两个主要原因:

1、内存泄漏,大量无用对象未及时回收,导致后续申请内存失败。

2、BitMap大对象,几个大图同时加载很容易触发OOM。

为了空出足够的内存供前台进程使用,Android会定时进行CHECK进程树,然后杀死优先级别不高的进程。而进程的优先级别是按照属性 oom_adj 来判断的。oom_adj数值越低,越不会被杀死。

3. oom_adj 的值是如何赋予的

oom_adj的数字大致为这几种:

FOREGROUND_APP_ADJ 0 前台进程,正在活动的Activity或者使用startForeground的Service
VISIBLE_APP_ADJ 1 可见进程,不可操作的Activity,但是可见
SECONDARY_SERVER_ADJ 2 拥有后台服务器的进程
HIDDEN_APP_MIN_ADJ 7 Activity没有完全退出,直接采用 moveTaskToBack 到HOME的进程
CONTENT_PROVIDER_ADJ 14 内容提供进程
EMPTY_APP_ADJ 15 空程序,既不提供服务,也不提供内容
CORE_SERVER_ADJ -12 系统进程
SYSTEM_ADJ -16 系统核心服务(进程永远不会被杀掉)

当系统的内存不足的时候,那么就会杀死发送KILL SIGNAL, 杀死一些优先级别低的进程,用来提供足够的内存给前台进程使用。

用命令可以查看进程的优先级的值:

adb shell dumpsys activity|grep oom_adj

查看进程命令:

adb shell dumpsys activity processes

注意:

  • Low memory killer 是定时进行检查。

  • Low memory killer 主要是通过进程的oom_adj 来判定进程的重要程度。这个值越小,程序越重要,被杀的可能性越低。

  • oom_adj的大小和进程的类型以及进程被调度的次序有关。

4. LMK的工作机制

LMK开始工作时,首先根据阈值表确定当前的警戒级数,则高于警戒级数的进程是待杀的范围。

然后遍历所有进程的oom_adj值,找到大于min_adj的进程,若找到多个,则把占用进程最大的进程存放在selected中。最关键的一步就是,发送SIGKILL信息,杀掉该进程。

5.Android进程优先级

5.1 Android进程的优先级

一般情况下,Android会尽可能的保持应用进程,但在特定的场景会对进程进行Kill,例如为了清除旧进程来回收内存等。为了区分哪些进程最先被回收清理,而哪些不会,有一个优先级别,这就是Android的进程优先级,具体包括以下5种(优先级从高到低)。

  • Foreground/Activate process 前台进程。用户当前操作的进程,包括用户正在交互的Activity,绑定用户正在交互Activity的Service,使用startForeground的Service,正在执行onReceive的BroadcastReceiver等。
  • Visible process 可见进程。会影响用户所见内容的进程,如onPause状态的Activity等。
  • Service process 服务进程。后台服务,如正在运行startService启动的Service。
  • Background process 后台进程。对用户交互无影响,如onStop状态的Activity等。
  • Empty process 空进程。一般用作缓存以缩短下次启动时间,系统往往会终止这些空进程。

5.2. Android进程的回收策略

Android主要通过LMK(Low Memory Killer)来对进程进行回收管理,LMK是在Android系统内存不足而选择kill部分进程释放空间,生死大权的决定者,其基于Linux的OOM机制,LMK通过oom_adj与占用内存的大小决定要杀死的进程,oom_adj值越小,越不容易被杀死。上面的几种进程形态对于的不同的oom_adj值。前台进程的优先级为0,普通service的进程优先级是8。

5.3 保活的方法

一方面提高进程优先级,降低被系统kill的概率。另一方面,在App被杀死以后进行拉活。知道了原理我们就可以采用一定的策略来提高应用的存活几率。

二、方法篇

进程保活说白了就是保证自己App进程不死,App被杀死有以下几种可能:

  • 被系统杀死
  • 被用户杀死
  • 被竞争对手杀死

了解LMK机制后,就可以对系统杀死的情况做相对应的优化。

  1. 通过在androidmanifest.xml中的application标签中加入android:persistent="true"属性后的确就能够达到保证该应用程序所在进程不会被LMK杀死。

但有个前提就是应用程序必须是系统应用,也就是说应用程序不能采用通常的安装方式。必须将应用程序的apk包直接放到/system/app目录下。而且必须重启系统后才能生效。

应用场景:定制TV端、平板端和手机端预装系统软件。

关键词:加入白名单、成为系统软件。

有些手机厂商把这些知名的app放入了自己的白名单中,保证了进程不死来提高用户体验(如微信、QQ、百度全家桶等在小米的白名单中)。如果从白名单中移除,他们终究还是和普通app一样躲避不了被杀的命运。

  1. 在程序中考虑异常处理,如恢复数据状态
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...@Override
public void onSaveInstanceState(Bundle savedInstanceState) {// 保存用户自定义的状态savedInstanceState.putInt(STATE_SCORE, mCurrentScore);savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);// 调用父类交给系统处理,这样系统能保存视图层次结构状态super.onSaveInstanceState(savedInstanceState);
}

说明:Activity 被系统回收了,在回收之前保存当前状态。
重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法会在Activity被回收前调用。
通过重写onRetoreInstanceState()方法可以从中提取保存好的数据。

  1. 程序退出时 做类似Home处理。将程序退到后台而不是kill程序。

在根Activity中重写后退按钮响应事件,当按后退按钮的时候把Activity退置到后台

     @Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {moveTaskToBack(true);        return true;}return super.onKeyUp(keyCode, event);}

其中的moveTaskToBack

   /*** Move the task containing this activity to the back of the activity* stack.  The activity's order within the task is unchanged.** @param nonRoot If false then this only works if the activity is the root*                of a task; if true it will work for any activity in*                a task.** @return If the task was moved (or it was already at the*         back) true is returned, else false.*/
public boolean moveTaskToBack(boolean nonRoot) {try {return ActivityManager.getService().moveActivityTaskToBack(mToken, nonRoot);} catch (RemoteException e) {// Empty}return false;}

说明:当nonRoot 为 false 时,当前activity必须为栈底,也就是最底层的activity,如果其他activity没有及时finish掉,就会出现异常,导致崩溃等情况的发生;nonRoot 为 true 时,不需要考虑当前activity是否在栈底。

  1. 程序性能优化,回归问题的本质。

系统统内存不足的时候肯定优先杀死这些占用内存高的进程来腾出资源。所以,为了尽量避免后台UI进程被杀,需要尽可能的释放一些不用的资源,尤其是图片、音视频之类的。对此,我们要想程序不被杀死,必须当前程序的内存占空间有比其他程序小才有竞争力不被优化kill掉。

最后在进一步总结LMK的机制和实际运用的意义时,看看这个博主是如何总结的:

关于了解LMK之后的内存管理建议:

  1. 我个人是长期在手机厂商从事APP和framework开发的。从外部来看,如果一个应用的内存总是不够用而又经常被回收,那么是可以从各个层面来缓解这种情况的——设置应用进程的oom_adj为更低(这种修改不仅可在底层也可在app层进行),修改各等级阀值等等,这是在不涉及应用本身修改的情况下,能做出的有限修改。可惜对于日常的应用开发者来说,这绝对不是康庄大道。
  2. 对于一般的应用开发者而言,安卓设备的底层已经封闭,甚至ROOT权限也无法获得,他们能做的更多是从应用自身进行优化,来使得应用更不容易被杀死回收。要做到这一点,就要深刻理解LMK的权重系统。比如运行那些需要后台运行的任务,用service而不要用后台进程;又比如如果你在开发输入法等应用,你自然能通过某些设置使得它变成高优先级的可视进程而不是后台进程。
  3. 当然,既然有所谓阀值,最治本的方法当然是减少进程的内存占用。作为普通应用开发者,你不能默认自己的应用能始终在前台,更不可能无限制地重启自己的进程(最好别这么干),提高应用各层级的阀值,锲而不舍地减少应用各个部分所占用的内存,并更顺畅地帮助内存的释放(是的。。。JAVA),才是开发内存占用小,运行稳定顺畅的好应用的优秀开发者素质。

三、总结

了解Android LMK机制后,有助于在开发程序时 对系统的内存回收机制采取一定的措施来提高程序的体验性,同时最核心的问题还是在程序的开发内功上做指导意义,毕竟,如何管理好内存,是我们一直需要探讨和实践的问题。未完待续……

参考资料:

1.onSaveInstanceState()和onRestoreInstanceState()使用详解

2.Android之进程回收机制LMK(Low Memory Killer)

3.Android APP开发的内存管理与优化之一 ——LowMemory Killer

你了解Android LMK机制么?相关推荐

  1. android lmk机制,android LMK(low memory killer) 工作机制

    Android Kernel 会定时执行一次检查,杀死一些进程,释放掉内存. 那么,如何来判断,那些进程是需要杀死的呢?答案就是我们的标题:Low memory killer机制. Low memor ...

  2. Android LMK机制

    前言 基于andorid4.4源码阅读和解说 关于LMK 网上已经有很多介绍,很多地方我就不做重复介绍, 这篇文章主要是介绍个人对LMK的理解和一些之前自己的疑惑 1 LMK是什么? 2 adj 是什 ...

  3. Android LMK

    2019独角兽企业重金招聘Python工程师标准>>> Android LMK 大家都知道,Android App在退出页面的时候,是不会杀死进程的,这就可能导致Memory不足.为 ...

  4. Android的LMK机制学习笔记

    初识Android的LMK机制 一.文章背景 1.1 LMK中kill进程的关键log(原生系统):![LMK中kill进程的关键log](https://img-blog.csdnimg.cn/78 ...

  5. 理解Android安全机制

    本文从Android系统架构着手,分析Android的安全机制以SE Android,最后给出一些Android安全现状和常见的安全解决方案. 1.Android系统架构 Android采用分层的系统 ...

  6. Android LowmemoryKiller机制

    为什么引入LowmemoryKiller? 进程的启动分冷启动和热启动,当用户退出某一个进程的时候,并不会真正的将进程退出,而是将这个进程放到后台,以便下次启动的时候可以马上启动起来,这个过程名为热启 ...

  7. Android消息机制Handler用法

    这篇文章介绍了Android消息机制Handler用法总结,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 1.简述 Handler消息机制主要包括: Messa ...

  8. 【腾讯Bugly干货分享】经典随机Crash之二:Android消息机制

    为什么80%的码农都做不了架构师?>>>    本文作者:鲁可--腾讯SNG专项测试组 测试工程师 背景 承上经典随机Crash之一:线程安全 问题的模型 好几次灰度top1.top ...

  9. Android刷新机制-View绘制原理

    Android刷新机制-View绘制原理 Android刷新机制-SurfaceFlinger原理 Android刷新机制-Choreographer原理 一.概述 本文将从startActivity ...

最新文章

  1. hibernate-session中的方法
  2. Flask框架-基本使用
  3. 【bzoj3866】The Romantic Hero dp
  4. python代码案例详解-新手必学Python爬虫之Scrapy框架案例详解
  5. Vue-员工管理系统
  6. SAP ABAP 中一些常用函数
  7. [SDOI2011]计算器 BSGS
  8. Java内部类详解(转)
  9. 英伟达自动驾驶技术:用于自动驾驶汽车的端到端深度学习
  10. Spring MVC No converter found for return value of type
  11. 刷题upupup【Java中Queue、Stack、Heap用法总结】
  12. Foundation - NSDate
  13. 用.htaccess禁止某IP访问
  14. 03.09 随手记(Mock数据生成器,Easy Mock基本使用)
  15. mysql sql联合查询语句_MySQL多表联合查询sql语句
  16. photoshop cs6视频教程(从入门到精通)
  17. 分享【珠海】联想 IBM X3850 X6服务器维修真实案例
  18. Python画美队盾牌
  19. 移动端seo如何优化,需要做单独的m域名移动端googleseo优化吗?
  20. 复旦黄萱菁:顶会也喜欢“搞事情”文章,提示学习等已成为NLP领域的研究重点...

热门文章

  1. bios 刷 灵耀14_华硕灵耀14 2020深度体验——这才是正统轻薄本
  2. Windows下SPONGE及配套软件的安装
  3. 开题报告中外文文献的查询和引用
  4. 修改input标签的提示文本的颜色
  5. Python实现全自动输入文本
  6. Mendeley管理参考文献
  7. TM4C123-TivaWare中函数名与函数指针在ROM中的映射
  8. 微信小程序接入Vant Weapp
  9. 搞定 psp2000 无线上网问题
  10. 如何使用Arduino开发板连接NEO-6M GPS模块