当前位置: 首页 > 编程日记 > 正文

怎样使一个Android应用不被杀死?(整理)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

方法
对于一个service,可以首先把它设为在前台运行:
public void MyService.onCreate() {
            super.onCreate();
              Notification notification = new Notification(android.R.drawable.my_service_icon,
                           "my_service_name",
                            System.currentTimeMillis());
              PendingIntent p_intent = PendingIntent.getActivity(this, 0,
                               new Intent(this, MyMainActivity.class), 0);
              notification.setLatestEventInfo(this, "MyServiceNotification, "MyServiceNotification is Running!",     p_intent);
              Log.d(TAG, String.format("notification = %s", notification));
              startForeground(0x1982, notification);     // notification ID: 0x1982, you can name it as you will.
}

-------------------------------
相较于/data/app下的应用,放在 /system/app 下的应用享受更多的特权,比如若在其Manifest.xml文件中设置persistent属性为true,则可使其免受out-of-memory killer的影响。如应用程序'Phone'的AndroidManifest.xml文件:
       <application android:name="PhoneApp"
                                  android:persistent="true"
                                 android:label="@string/dialerIconLabel"
                                 android:icon="@drawable/ic_launcher_phone">
                 ...
       </application>
设置后app提升为系统核心级别,任何情况下不会被kill掉, settings->applications里面也会屏蔽掉stop操作。

这样
设置前的log:   Proc #19: adj=svc  /B 4067b028 255:com.xxx.xxx/10001 (started-services)
# cat /proc/255/oom_adj
4
设置后的log:  PERS #19: adj=core /F 406291f0 155:com.xxx.xxx/10001 (fixed)
# cat /proc/155/oom_adj
-12                #  这是CORE_SERVER_ADJ
注:init进程的oom_adj为-16(即SYSTEM_ADJ): cat  /proc/1/oom_adj

Android相关部分分析:
在文件frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中有以下的代码:
       final ProcessRecord addAppLocked(ApplicationInfo info) {
               ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);

               if (app == null) {
                       app = newProcessRecordLocked(null, info, null);
                       mProcessNames.put(info.processName, info.uid, app);
                       updateLruProcessLocked(app, true, true);
               }       

               if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
                               == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
                        app.persistent = true ;
                        app.maxAdj = CORE_SERVER_ADJ                        // 这个常数值为-12。
               }       
               if (app.thread == null && mPersistentStartingProce sses.indexOf(app) < 0) {
                       mPersistentStartingProce sses.add(app);
                       startProcessLocked(app, "added application", app.processName);
               }       

               return app;
       }

可见要想成为core service (即app.maxAdj = CORE_SERVER_ADJ(-12)),应用程序需要FLAG_SYSTEM和FLAG_PERSISTENT两个标志,FLAG_SYSTEM指的是应用位于/system/app下,FLAG_PERSISTENT就是指persistent属性。

而对于frameworks/base/services/java/com/android/server/SystemServer.java,则调用
             ActivityManagerService.setSystemProcess();
把自己的 app.maxAdj 设置成SYSTEM_ADJ,即-16。

原理
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。由此带来三个问题:
       1) 回收规则:   什么时候回收与回收哪一个?
       2) 避免误杀:   如何阻止被回收?
       3) 数据恢复与保存:   被回收了怎么办?
 
Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
     1.前台进程( FOREGROUND_APP)
     2.可视进程(VISIBLE_APP )
     3. 次要服务进程(SECONDARY_SERVER )
     4.后台进程 (HIDDEN_APP)
     5.内容供应节点(CONTENT_PROVIDER)
     6.空进程(EMPTY_APP)
 
特征:
1.如果一个进程里面同时包含service和可视的activity,那么这个进程应该归于可视进程,而不是service进程。
2.另外,如果其他进程依赖于它的话,一个进程的等级可以提高。例如,一个A进程里的service被绑定到B进程里的组件上,进程A将总被认为至少和B进程一样重要。
3.系统中的phone服务被划分到前台进程而不是次要服务进程.
 
在android中,进程的oom_adj值也就代表了它的优先级。oom_adj值越高代表该进程优先级越低。文件/init.rc中有以下属性设置:
       setprop ro.FOREGROUND_APP_ADJ            0
       setprop ro.VISIBLE_APP_ADJ                                         1
       setprop ro.SECONDARY_SERVER_ADJ    2
       setprop ro.HIDDEN_APP_MIN_ADJ                     7
       setprop ro.CONTENT_PROVIDER_ADJ   14
       setprop ro.EMPTY_APP_ADJ                                       15
/init.rc中,将PID为1的进程(init进程)的oom_adj设置为SYSTEM_ADJ(-16):
       # Set init its forked children's oom_adj.
       write /proc/1/oom_adj -16

查看本机设置:
cat /sys/module/lowmemorykiller/parameters/adj
0,1,2,7,14,15
 
回收时机:
文件/init.rc中:
     setprop ro.FOREGROUND_APP_MEM             1536           //       6M
     setprop ro.VISIBLE_APP_MEM                                2048         //       8M
     setprop ro.SECONDARY_SERVER_MEM     4096         //   16M
     setprop ro.HIDDEN_APP_MEM                                         5120         //   20M
     setprop ro.CONTENT_PROVIDER_MEM       5632         //   22.4M
     setprop ro.EMPTY_APP_MEM                                           6144         //   24M
这些数字也就是对应的内存阈值,一旦低于该值,Android便开始按顺序关闭相应等级的进程。
注意这些数字的单位是page: 1 page = 4 kB。所以上面的六个数字对应的就是(MB): 6,8,16,20,22,24。
 
查看现在的内存阈值设置:
cat /sys/module/lowmemorykiller/parameters/minfree

要想重新设置该值(对应不同的需求):
echo     "1536,2048,4096,5120,15360,23040">/sys/module/lowmemorykiller/parameters/minfree
这样当可用内存低于90MB的时候便开始杀死"空进程",而当可用内存低于60MB的时候才开始杀死"内容供应节点"类进程。
 
具体的回收实现 在ActivityManagerService.java中的函数trimApplications():
     1.首先移除package已被卸载的无用进程;
     2.基于进程当前状态,更新oom_adj值,然后进行以下操作:
                 1) 移除没有activity在运行的进程;
                 2) 如果AP已经保存了所有的activity状态,结束这个AP。
     3. 最后,如果目前还是有很多activities 在运行,那么移除那些activity状态已经保存好的activity。
 

更新oom_adj的值:
在ActivityManagerService.java文件的ComputeOomAdjLocked() 中计算出进程的oom_adj,例如:
         if (app == TOP_APP) {
                       // The last app on the list is the foreground app.
                       adj = FOREGROUND_APP_ADJ;
                       app.adjType = "top-activity";
               }
 
Android kernel中的low memory killer
Android的Low Memory Killer根据需要(当系统内存短缺时)杀死进程释放其内存,源代码在kernel/drivers/misc/lowmemorykiller.c中。简单说,就是寻找一个最合适的进程杀死,从而释放它占用的内存。
最合适的进程是:
     •   oom_adj越大
     •   占用物理内存越多
 
一旦一个进程被选中,内核会发送SIGKILL信号将之杀死:
     for_each_process(p) {
               ……
               if(selected == NULL ||     p->oomkilladj > selected->oomkilladj ||
                     (p->oomkilladj == selected->oomkilladj && tasksize > selected_tasksize))
               {
                         selected = p;
               }
     }
     if(selected != NULL) {
               force_sig(SIGKILL, selected);
     }
 
查看LRU列表:adb shell dumpsys activity
当activitydemo在前台时: 
包含Service的进程的优先级比较高,在computeOomAdjLocked中将其分为了两小类:
           static final int MAX_SERVICE_INACTIVITY = 30*60*1000;                                 
         if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
                             if (adj > SECONDARY_SERVER_ADJ) {
                                                       adj = SECONDARY_SERVER_ADJ;
                                                       app.adjType = "started-services";
                                                       app.hidden = false;
                             }
           }
           if (adj > SECONDARY_SERVER_ADJ) {
                                               app.adjType = "started-bg-services";
           }
 

完全让进程不被kill是不可能的,我们可以通过一些操作,使进程被kill的几率变小:
   1) 提高进程的优先级:
               * 后台操作采用运行于前台的Service形式,因为一个运行着service的进程比一个运行着后台activity的等级高;
               * 按back键使得进程中的activity在后台运行而不是destory,需重载back按键(没有任何activity在运行的进程优先被杀).
               * 依赖于其他优先级高的进程;

   2) 强制修改进程属性:
               * 在进程中设置:setPersistent(true);
               * 在Manifest文件中设置(如上)。

转载于:https://my.oschina.net/lhjtianji/blog/157654

相关文章:

Ubuntu 14.04 64位机上用Caffe+MNIST训练Lenet网络操作步骤

1. 将终端定位到Caffe根目录&#xff1b; 2. 下载MNIST数据库并解压缩&#xff1a;$ ./data/mnist/get_mnist.sh 3. 将其转换成Lmdb数据库格式&#xff1a;$ ./examples/mnist/create_mnist.sh 执行完此shell脚本后&#xff0c;会在./examples/mnist下增加两个新…

IJCAI 2019:中国团队录取论文超三成,北大、南大榜上有名

作者 | 神经小姐姐来源 | HyperAI超神经&#xff08; ID: HyperAI )【导读】AI 顶会 IJCAI 2019 已于 8 月 16 日圆满落幕。在连续 7 天的技术盛会中&#xff0c;与会者在工作坊了解了 AI 技术在各个领域的应用场景&#xff0c;聆听了 AI 界前辈的主题演讲&#xff0c;还有机会…

适合小小白的完整建设流程

时常有中小企业建站的客户问到我要自己建网站&#xff0c;应该怎么开始&#xff1f;建站有一定的技术门槛&#xff0c;首先要明白建站要做的哪些事情&#xff0c;里面有哪些坑&#xff0c;把流程弄清楚了才能避免入坑&#xff0c;半途而废&#xff01;下面总结了建站的流程还有…

ios项目文件结构 目录的整理

2019独角兽企业重金招聘Python工程师标准>>> /<ProjectName>/Shared/Application # App delegate and related files/Controllers # Base view controllers/Models # Models, Core Data schema etc/Views # Shared views/Libr…

重磅!全球首个可视化联邦学习产品与联邦pipeline生产服务上线

【导读】作为全球首个联邦学习工业级技术框架&#xff0c;FATE支持联邦学习架构体系与各种机器学习算法的安全计算&#xff0c;实现了基于同态加密和多方计算&#xff08;MPC&#xff09;的安全计算协议&#xff0c;能够帮助多个组织机构在符合数据安全和政府法规前提下&#x…

SpringBoot之集成swagger2

maven配置 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.5.0</version> </dependency> <dependency><groupId>io.springfox</groupId><artifact…

Windows Caffe中MNIST数据格式转换实现

Caffe源码中src/caffe/caffe/examples/mnist/convert_mnist_data.cpp提供的实现代码并不能直接在Windows下运行&#xff0c;这里在源码的基础上进行了改写&#xff0c;使其可以直接在Windows 64位上直接运行&#xff0c;改写代码如下&#xff1a;#include "stdafx.h"…

关于less在DW中高亮显示问题

首先&#xff0c; 找到DW 安装目录。 Adobe Dreamweaver CS5.5\configuration\DocumentTypes 中的&#xff0c;MMDocumentTypes.xml 这个文件&#xff0c;然后用记事本打开&#xff0c;查找CSS 把 CSS 后边加上&#xff0c;less 然后到。C:\Users\Administrator\AppData\Roamin…

Windows7 64bit VS2013 Caffe train MNIST操作步骤

1. 使用http://blog.csdn.net/fengbingchun/article/details/47905907中生成的Caffe静态库&#xff1b; 2. 使用http://blog.csdn.net/fengbingchun/article/details/49794453中生成的LMDB数据库文件&#xff1b; 3. 新建一个train_mnist控制台工程&#…

NLP机器翻译深度学习实战课程基础 | 深度应用

作者 | 小宋是呢来源 | CSDN博客0.前言深度学习用的有一年多了&#xff0c;最近开始 NLP 自然处理方面的研发。刚好趁着这个机会写一系列 NLP 机器翻译深度学习实战课程。本系列课程将从原理讲解与数据处理深入到如何动手实践与应用部署&#xff0c;将包括以下内容&#xff1a;…

个人站点渲染和跳转过滤功能

核心逻辑&#xff1a;在url里加入正则&#xff0c;匹配分类、标签、年月日和其后面的参数&#xff0c;在视图函数接收这些参数&#xff0c;然后进行过滤。 urls.py # 个人站点的跳转 re_path(r^(?P<username>\w)/(?P<condition>tag|category|archive)/(?P<pa…

三步10分钟搞定数据库版本的降迁 (将后台数据库SQL2008R2降为SQL2005版本)

三步10分钟搞定数据库版本的降迁 &#xff08;将SQL2008R2降为SQL2005版本&#xff09;转载原文&#xff0c;并注明出处&#xff01;虽无多少技术含量&#xff0c;毕竟是作者心血原创&#xff0c;希望理解。转自 http://blog.csdn.net/claro/article/details/6449824前思后想仍…

jdbc链接数据库

JDBC简介 JDBC全称为&#xff1a;Java Data Base Connectivity (java数据库连接&#xff09;&#xff0c;可以为多种数据库提供填统一的访问。JDBC是sun开发的一套数据库访问编程接口&#xff0c;是一种SQL级的API。它是由java语言编写完成&#xff0c;所以具有很好的跨平台特性…

Google Protocol Buffers介绍

Google Protocol Buffers(简称Protobuf)&#xff0c;是Google的一个开源项目&#xff0c;它是一种结构化数据存储格式&#xff0c;是Google公司内部的混合语言数据标准&#xff0c;是一个用来序列化&#xff08;将对象的状态信息转换为可以存储或传输的形式的过程&#xff09;结…

打造 AI Beings,和微信合作…第七代微软小冰的成长之路

8月15日&#xff0c; “第七代微软小冰”年度发布会在北京举行。本次发布会上&#xff0c;微软(亚洲)互联网工程院带来了微软小冰在 Dual AI 领域的新进展&#xff0c;全新升级的部分核心技术&#xff0c;最新的人工智能创造成果&#xff0c;以及更多的合作与产品落地。其中&am…

感知机介绍及实现

感知机(perceptron)由Rosenblatt于1957年提出&#xff0c;是神经网络与支持向量机的基础。感知机是最早被设计并被实现的人工神经网络。感知机是一种非常特殊的神经网络&#xff0c;它在人工神经网络的发展史上有着非常重要的地位&#xff0c;尽管它的能力非常有限&#xff0c;…

不甘心只做输入工具,搜狗输入法上线AI助手,提供智能服务

8月19日搜狗输入法上线了新功能——智能汪仔&#xff0c;在输入法中引入了AI助手&#xff0c;这是搜狗输入法继今年5月推出“语音变声功能”后又一个AI落地产品。 有了智能汪仔AI助手的加持后&#xff0c;搜狗输入法能够在不同的聊天场景&#xff0c;提供丰富多样的表达方式从…

可构造样式表 - 通过javascript来生成css的新方式

可构造样式表是一种使用Shadow DOM进行创建和分发可重用样式的新方法。 使用Javascript来创建样式表是可能的。然而&#xff0c;这个过程在历史上一直是使用document.createElement(style)来创建<style>元素&#xff0c;然后通过访问其sheet属性来获得一个基础的CSSStyle…

模板方法模式与策略模式的区别

2019独角兽企业重金招聘Python工程师标准>>> 模板方法模式&#xff1a;在一个方法中定义一个算法的骨架&#xff0c;而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下&#xff0c;重新定义算法中的某些步骤。 策略模式&#xff1a;定义一个…

简单明了,一文入门视觉SLAM

作者 | 黄浴转载自知乎【导读】SLAM是“Simultaneous Localization And Mapping”的缩写&#xff0c;可译为同步定位与建图。最早&#xff0c;SLAM 主要用在机器人领域&#xff0c;是为了在没有任何先验知识的情况下&#xff0c;根据传感器数据实时构建周围环境地图&#xff0c…

大主子表关联的性能优化方法

【摘要】主子表是数据库最常见的关联关系之一&#xff0c;最典型的包括合同和合同条款、订单和订单明细、保险保单和保单明细、银行账户和账户流水、电商用户和订单、电信账户和计费清单或流量详单。当主子表的数据量较大时&#xff0c;关联计算的性能将急剧降低&#xff0c;在…

Windows7上配置Python Protobuf 操作步骤

1、 按照http://blog.csdn.net/fengbingchun/article/details/8183468 中步骤&#xff0c;首先安装Python 2.7.10&#xff1b; 2、 按照http://blog.csdn.net/fengbingchun/article/details/47905907 中步骤&#xff0c;配置、编译Protobuf&#xff1b; 3、 将(2)中生成的pr…

鲜为人知的静态、命令式编程语言——Nimrod

Nimrod是一个新型的静态类型、命令式编程语言&#xff0c;支持过程式、函数式、面向对象和泛型编程风格而保持简单和高效。Nimrod从Lisp继承来的一个特殊特性抽象语法树&#xff08;AST&#xff09;作为语言规范的一部分&#xff0c;可以用作创建领域特定语言的强大宏系统。它还…

机器学习进阶-图像形态学操作-腐蚀操作 1.cv2.erode(进行腐蚀操作)

1.cv2.erode(src, kernel, iteration) 参数说明&#xff1a;src表示的是输入图片&#xff0c;kernel表示的是方框的大小&#xff0c;iteration表示迭代的次数 腐蚀操作原理&#xff1a;存在一个kernel&#xff0c;比如(3, 3)&#xff0c;在图像中不断的平移&#xff0c;在这个9…

无需成对示例、无监督训练,CycleGAN生成图像简直不要太简单

作者 | Jason Brownlee译者 | Freesia&#xff0c;Rachel编辑 | 夕颜出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】图像到图像的转换技术一般需要大量的成对数据&#xff0c;然而要收集这些数据异常耗时耗力。因此本文主要介绍了无需成对示例便能实现图…

Git使用常见问题解决方法汇总

1. 在Ubuntu下使用$ git clone时出现server certificate verification failed. CAfile:/etc/ssl/certs/ca-certificates.crt CRLfile: none 解决方法&#xff1a;在执行$ git clone 之前&#xff0c;在终端输入&#xff1a; export GIT_SSL_NO_VERIFY1 2. 在Windows上更新了…

服务器监控常用命令

在网站性能优化中&#xff0c;我们经常要检查服务器的各种指标&#xff0c;以便快速找到害群之马。大多情况下&#xff0c;我们会使用cacti、nagois或者zabbix之类的监控软件&#xff0c;但是这类软件安装起来比较麻烦&#xff0c;在一个小型服务器&#xff0c;我们想尽快找到问…

Ubuntu下内存泄露检测工具Valgrind的使用

在VS中可以用VLD检测是否有内存泄露&#xff0c;可以参考http://blog.csdn.net/fengbingchun/article/details/44195959&#xff0c;下面介绍下Ubuntu中内存泄露检测工具Valgrind的使用。Valgrind目前最新版本是3.11.0&#xff0c; 可以从http://www.valgrind.org/ 通过下载源码…

数据为王的时代,如何用图谱挖掘商业数据背后的宝藏?

这是一个商业时代&#xff0c;一个数据为王的时代&#xff0c;也是一个 AI 迎来黄金发展期的时代。据史料记载&#xff0c;商业在商朝已初具规模。斗转星移&#xff0c;时光流转&#xff0c;到 2019 年&#xff0c;商业形式已发生翻天覆地的变化&#xff0c;但是商业的本质——…

旋转卡壳——模板(对踵点)

这东西学了我大概两天吧。。其实不应该学这么久的&#xff0c;但是这两天有点小困&#xff0c;然后学习时间被削了很多\(QwQ\) 说几个坑点。 - 对于题目不保证有凸包的情况&#xff0c;要选用左下角的点&#xff0c;而非单纯的最下边的点构造凸包。 - 对于凸包中只有\(1/2\)个点…