不知不觉间 Android 陷入了一个关于「后台」的怪圈:一边各大厂商陆续推出了 12G RAM 的手机,另一边你刚刚放到后台的下载任务没有如预期那样后台挂机下载,打开微信发现还得陪启动画面的孤独小人共赏蓝色星球、按照教程辛辛苦苦做了半个小时的 Tasker 规则、却没有按照计划自动执行……
于是一个耳熟能详的句子开始在我们脑海中成型—— 我的后台又被「杀」了 。
应用开发者的「控诉」
遇到上述问题的人不止你一个,很多人选择向这些应用的开发者反馈问题,殊不知问题其实不在应用本身。
Android 平台著名睡眠追踪应用 Sleep as Android 的开发团队 Urbandroid Team 不堪其扰,索性上线了一个名为「别『杀』我应用」的网站,矛头直指手机厂商糟糕的后台管理机制。
以三星为例,Urbandroid Team 称,三星的部分机型在升级到基于 Android 9 的 One UI 后「杀后台」现象变得尤为严重,自适应电池(Adaptive Battery)机制相比原生 Android 变得尤为激进,3 天内没有启动过的应用甚至无法从后台再次启动。最为糟糕的情况是,如果你安装了一个可以自动跳过周末的第三方闹钟,那这个闹钟应用很有可能不会像系统闹钟那样在下周一早上准时响起……
正如「别『杀』我应用」网站上控诉的那样,拥有类似机制的还包括华为、一加、小米、华硕等等手机厂商的定制版 Android 系统,它们管理后台的方式大同小异,但都秉承着 iOS 上那一套「划掉就杀掉」的原则——当我们把某款应用的任务卡片从多任务界面划去,它们也就彻底从手机后台中抹除掉了。
这里你可能会问很多问题:
我们得从一些基础的原理说起。
Android 的内存回收机制
在 官方文档 中,Google 将「不受应用自身直接控制的应用进程生命周期」描述为 Android 最为基础也最为独特的核心特性,这里我们不妨将「应用进程生命周期」暂时理解为文章开头和第一部分所说的「后台」或「后台进程(process)」。
所以 Android 应用的后台进程去留本应是由 Android 系统来决定的 。
当可用运行内存空间不足时,Android 系统会自行决定对特定应用后台进程占用的空间进行回收释放,这个过程中 Android 挥舞着的那把大刀,叫做 LMK(Low Memory Killer)。那 LMK 又是如何判断哪些应用可以被「杀」掉、哪些应用又该暂时放过的呢?
每个应用都有各种各样的组成部分,其中特定组件的运行状态共同组成了一套供 LMK 进行内存回收的「优先级」参考,包括:前台进程、可见进程、服务进程和缓存进程。
前台进程、可见进程和服务进程往往与我们正在手机上执行的 *** 作直接或间接相关 ,比如正在前台供我们交互和 *** 作的活动窗口(Activity)、正在通过广播接收器(BroadcastReceiver)等待触发的 Tasker 规则、正在后台通过 Wi-Fi 网络自动上传备份照片的 Google Photos 以及前面提到的有待触发的闹钟等等。这些进程优先级从高到低依次递减,LMK 一般不会触及。
缓存进程则是那些暂时放在运行内存中的部分,也是和本文探讨话题主要相关的重点 。
只有在极端情况下 ,比如 Android 系统在回收掉所有缓存进程后发现空闲内存依然不够用(比如在低内存的「老爷机」上运行《崩坏 3》),这时 LMK 才会根据优先级继续对服务进程、可见进程和前台进程采取回收策略。 而当这些我们在正常使用中能够直观感受到的进程都不得不被被回收时 ,文章开头提到的微信重载、音乐中断、下载消失等等现象也就出现了。
谁动了你的后台
在可用内存充裕的情况下遭遇「杀后台」现象,一方面可能是 LMK 这把「大刀」出了问题(常见于 Android 9 时期的 Pixel 3 用户),另一方面则有可能是其它规则额外干预了 Android 系统正常的内存回收机制。
这里提到的「其它规则」主要有两种形式,一种类似部分华为设备上预装的「省电精灵」,它会将所有没有加入后台白名单中的应用后台统统清除,另一种则依托于 Google 推出的 后台检查 、 后台限制 和 自适应电池 等功能进行「魔改」,让这些功能的实际效果远超预期,甚至达到意料之外的负面效果。
根据 Don't kill my app! 的统计,第二种后台干预机制在三星、一加和早期的诺基亚机型中常见,这里厂商们通常会用到一种类似「白名单」的方法来进行过滤。
以三星手机基于 Android 9 的 One UI 为例,除了微信、QQ 等国内常见应用,One UI 默认会为所有第三方应用关闭「允许后台活动」这一选项,同时开启「优化电池使用量」这一功能。
部分搭载氢 OS 的一加机型则将上面提到的应用进程进行拆分,除了基于原生 Android 的后台限制、电池优化,还有一套名为「自启动管理」的设置来对应用的自启动进行管理以及一套名为「深度优化」的电池优化机制,后者会造成很多智能手表、手环设备在一段时间后丢失与手机的蓝牙连接,最终导致睡眠追踪、运动记录等等功能的失效。
问题在于上述功能埋藏较深,一般用户在安装应用后往往不会第一时间前往设置,一加的氢 OS 更是以系统更新之后自动重置部分用户设置闻名,那些需要在后台正常工作的应用,因此也被都被直接扔进了原生 Android 中用来限制「毒瘤」应用的「黑箱」里。
换句话说,国内大部分定制 ROM 在后台管理这件事情上都选择采用一种「 宁肯错杀一千不肯放过一个 」的做法。
关联阅读: 控制频繁启动的「毒瘤」,Android 90 用这些方法让你的手机更省电
多任务管理还是后台管理?
从某种程度上来说,国产手机厂商在 Android 后台管理上的做法虽然偏激,但它们都是国内特殊生态下的产物 。
一方面,尽管 Google 为 Android 设想了一套非常理想化的应用运行与后台管理机制 ,但大多数于原生 Android 中行之有效的后台管理机制在国内似乎都会变成「鸡肋」。
如果 Google 有 100 种提升 Android 应用运行效率,保证后台绿色、纯净的方法,国内毒瘤应用开发商就有 101 种绕过这些限制的方法。
借助共用的第三方推送服务实现链式唤醒、借助透明的悬浮窗保证后台存活、通过不断获取定位的方式来避免进程被系统回收……不管是出于实现消息推送这样单纯的目的还是为了不断唤醒用户设备以实现 KPI 目标这种下作的行为,在国内 Android 生态中均有出现。
虽然国内外的具体环境有所不同,但这类设计不规范的 Android 应用带来的问题却是一样的,这类应用放在后台不仅不会为我们带来便利,反而还会因为频繁唤醒设备带来不小的耗电问题。待机续航问题作为悬在国产 Android 机头顶的几把利剑之一,手机厂商不得不各自从系统层面推出自家的应对机制——这就有了上面提到的各种偏激式的后台管理方法。
另一方面,这里还涉及到一个非常重要的概念区分 :多任务管理和后台管理究竟是不是一回事?
国内 Android 生态由于早期受 iOS 影响较深,无论是开发商还是用户都更倾向于把「将应用卡片从多任务列表里划掉」的行为理解为清除对应用的后台进程。在上面提到的特殊生态环境的影响之下,这里被清除的后台进程往往又包括那些用于保证应用后台运行的可见进程、服务进程乃至前台进程在内。
在酷安应用市场,甚至还有得以在原生 Android 上实现类似「划掉卡片即停止运行」效果的应用,iOS 的后台管理理念在国内有多么深入人心可见一斑。
但这种后台管理理念却与 Google 对 Android 的多任务管理设计方式相悖。Google 一直以来都将 Android 手机上呼出任务卡片的那个界面叫做 Recents,最近几个版本的 Android 系统更是将其本地化为「概览」。结合 Google 在 Android 9 和 Android 10 手势交互上的变革,注重多任务管理而非后台管理的意图也越发明显。
当最近运行的应用以一张张卡片的形式呈现在我们面前时,Google 想要呈现的是一个能够让我们在不同任务间快速切换的多任务交互,而在理想状态下,后台管理则是交由系统处理、完全不应被用户感知的。
至于如何理性看待 Android 平台的后台管理,这里我们不妨借用绿色守护开发者 @OasisFeng 在「Android 多任务界面的划除交互」这个话题上的 答疑 来回答这个问题:
换句话说, 今后绝大部分需要在海外市场搭载 Google 服务上市的手机都必须满足这个要求 。
小结
就在上周三(9 月 25 日),酝酿已久的安卓统一推送联盟正式宣布收到华为、OPPO、一加和 realme 四家公司的进度确认,虽然 Google 的缺席也让国内 Android 生态也变得异常复杂,但国内 Android 设备也能用上的统一推送服务也算是终于迈出了具有实际意义的第一步。
只是距离转变人们对 Android「杀后台」这件事的看法依然还有很长的路要走。事实上,国内早在四五年前就出现过一次对「Android 需不需要『杀后台』」问题的科普,但收效甚微,盲从 iOS 设计风格和交互逻辑国内 Android 厂商要负很大一部分责任。
希望靠谱、省电的统一推送系统能成为改观的第一步,也希望 @OasisFeng 口中那个甚至可以跨越设备重启恢复「后台状态」的理想化生态早日到来——至于当下,我们依然只能见招拆招,遇到应用无法正常执行后台任务时打开手机设置仔细翻找、设置,把它们扔进白名单或是给它们的后台卡片套个「锁」……
下载、安装了一款非白名单应用,该如何确保它不被「杀后台」呢?欢迎在评论区把你的设置方法分享给大家。
内存优化就是对内存问题的一个预防和解决,做内存优化能让应用挂得少、活得好和活得久。
挂的少:
“挂”指的是 Crash,内存问题导致 Crash 的具体表现就是内存溢出异常 OOM。
活得好:
活得好指的是使用流畅,Android 中造成界面卡顿的原因有很多种,其中一种就是由内存问题引起的。内存问题之所以会影响到界面流畅度,是因为垃圾回收(GC,Garbage Collection),在 GC 时,所有线程都要停止,包括主线程,当 GC 和绘制界面的 *** 作同时触发时,绘制的执行就会被搁置,导致掉帧,也就是界面卡顿。
活得久:
活得久指的是我们的应用在后台运行时不会被干掉。Android 会按照特定的机制清理进程,清理进程时优先会考虑清理后台进程。清理进程的机制就是LowMemoryKiller。在 Android 中不同的进程有着不同的优先级,当两个进程的优先级相同时,低杀会优先考虑干掉消耗内存更多的进程。也就是如果我们应用占用的内存比其他应用少,并且处于后台时,我们的应用能在后台活下来,这也是内存优化为我们应用带来竞争力的一个直接体现。
内存占用是否越少越好?
当系统 内存充足 的时候,我们可以多用 一些获得更好的性能。当系统 内存不足 的时候,我们希望可以做到 ”用时分配,及时释放“。内存优化并不能一刀切。
我们都知道,应用程序的内存分配和垃圾回收都是由Android虚拟机完成的,在Android 50以下,使用的是Dalvik虚拟机,50及以上,则使用的是ART虚拟机。
Android虚拟机Dalvik和ART
1、内存区域划分
详细请看以下两篇文章(建议全看):
java内存四大区_JVM内存区域划分
Android 内存机制
2、内存回收
垃圾收集的标记算法(找到垃圾):
垃圾收集算法(回收垃圾):
引用类型:强引用、软引用、弱引用、虚引用
对象的有效性=可达性+引用类型
JAVA垃圾回收机制-史上最容易理解看这一篇就够了
Android:玩转垃圾回收机制与分代回收策略
android中还存在低杀机制,这种情况属于系统整机内存不足,直接把应用进程杀掉的情况。
Android后台杀死系列:LowMemoryKiller原理
1、内存溢出
系统会给每个App分配内存空间也就是heap size值,当app占用的内存加上申请的内存超过这个系统分配的内存限额,最终导致OOM(OutOfMemory)使程序崩溃。
通过命令 getprop |grep dalvikvmheapsize 可以获取系统允许的最大
注意:在设置了heapgrowthlimit的状况下,单个进程可用最大内存为heapgrowthlimit值。在android开发中,若是要使用大堆,须要在manifest中指定android:largeHeap为true,这样dvm heap最大可达heapsize。
关于heapsize & heapgrowthlimit
2、内存泄漏
Android系统虚拟机的垃圾回收是通过虚拟机GC机制来实现的。GC会选择一些还存活的对象作为内存遍历的根节点GC Roots,通过对GC Roots的可达性来判断是否需要回收。内存泄漏就是 在当前应用周期内不再使用的对象被GC Roots引用,造成该对象无法被系统回收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,使实际可使用内存变小。简言之,就是 对象被持有导致无法释放或不能按照对象正常的生命周期进行释放。
Android常见内存泄漏汇总
3、内存抖动
指的是在短时间内大量的新对象被实例化,运行时可能无法承载这样的内存分配,在这种情况下就会导致垃圾回收事件被大量调用,影响到应用程序的UI和整体性能,最终可能导致卡顿和OOM。
常见情况:在一些被频繁调用的方法内不断地创建对象。例如在View 的onDraw方法内new 一些新的对象。
注意内存抖动也会导致 OOM,主要原因有如下两点:
1、Android Studio Profiler
作用
优点
内存抖动问题处理实战
理解内存抖动的概念的话,我们就能明白只要能找到抖动过程中所产生的对象及其调用栈,我们就能解决问题,刚好Android Studio 的Porfiler里面的Memory工具就能帮我们记录下我们 *** 作过程中或静止界面所产生的新对象,并且能清晰看到这些对象的调用栈。
选择Profile 中 的Memory ,选择 Record Java/Kotlin allocations,再点击Record开始记录, Record Java/Kotlin allocations 选项会记录下新增的对象。
*** 作完成之后,点击如图所示的红脑按钮,停止记录。
停止记录后,我们就可以排序(点击 Allocations可以排序)看看哪些对象或基本类型在短时间被频繁创建多个,点击这些新增的对象就可以看到它的完成的调用链了,进而就找找到导致内存抖动的地方在哪里了。
2、利用DDMS 和 MAT(Memory Analyzer tool)来分析内存泄漏
我们利用工具进行内存泄漏分析主要是用对比法:
a先打开正常界面,不做任何 *** 作,先抓取一开始的堆文件。
b一顿胡乱 *** 作,回到原来 *** 作前的界面。主动触发一两次GC,过10秒再抓取第二次堆文件。
c通过工具对比,获取胡乱 *** 作后新增的对象,然后分析这些新增的对象。
DDMS作用:抓取堆文件,主动触发GC。(其实也是可以用Android Studio 的Profile里面的Memory工具来抓取堆文件的,但是我这边在利用Profile 主动触发gc 的时候会导致程序奔溃,也不知道是不是手机的问题,所以没用Android Studio的Profiler)
MAT作用:对堆文件进行对比,找到多出的对象,找到对象的强引用调用链。
以下是详细的过程:
步骤1打开DDMS,选择需要调试的应用,打开初始界面,点击下图的图标(Dump Hprof File)先获取一次堆文件。
步骤2对应用随便 *** 作后,回到一开始的界面,先多触发几次GC ,点击下图的图标(Cause Gc)来主动触发GC,然后再次点击 Dump Hprof File 图标来获取堆文件。
步骤3通过Android Studio Profile 或者 DDMS dump 的堆文件无法在MAT 打开,需要借助android sdk包下的一个工具hprof-convexe来转换。
格式为 hprof-conv 旧文件路径名 要转换的名称;
例如:hprof-conv 2022-04-13_17-54-40_827hprof changehprof
步骤4把两份堆文件导入MAT,然后选择其中第二次获取的堆文件,点击 如图所示的 Histogram查看。
步骤5点击下图图标,Compare To Another Heap Dump ,选择另一份堆文件。
6会得出下图所示的 Hitogram 展示,我们主要看Objects 这一列。 如下图所示 “+ 2” 则代表前面两份堆文件对比,这个对象多了两个,我们主要就是要分析这些多了出来,没有被回收的对象。
7加入我们从增加的对象中,看到了MainActivity ,则需要从一开始打开的Hitogram 展示里面找到这个对象的调用栈。如下图所示,搜索MainActivity
8看到下图所示解雇,然后鼠标右键点击下图红色圈圈着的MainActivity ,选择 Merger Shortest Paths to Gc Roots ,再选择 exclude all phantom/weak/soft etcreferences ,就可以看到这个MainActivity 对象的强引用链,至此我们就可以找到MainActivity对象是被什么引用导致无法回收了。
3、内存泄露检测神器之LeakCanary(线下集成)
自行学习了解,接入简单,使用简单,基本可以解决大部分内存泄漏问题。
github地址 : >
回收箱里的东西可以在优化大师文件目录里找到,系统自带的软件可以用RE管理器删除。目录是system/app,注意的是如果有与apk同名的odex文件,要连那个一起删,但是似乎不删也没嘛事。。删的时候要挂载文件目录类型为读写,否则不能删除。
以上就是关于为什么 12G 内存的 Android 手机依旧会被杀后台全部的内容,包括:为什么 12G 内存的 Android 手机依旧会被杀后台、Android App内存优化、安卓手机内存满了 安卓手机优化大师里的回收箱的东西怎么删 还有系统自带的怎么删 (已ROOT)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)