一、程序员速看!最新Android应用性能优化的九点建议
转自《 安卓尖端技术研究》转自《 安卓尖端技术研究》上一篇文章从Native角度讲解了Android进程管理的相关概念,本文将继续从上层的Framework中的进程启动、销毁场景和优先级处理、以及它们与四大组件的种种关联,来逐步解析Android进程管理的其他关键要素。进程的启动进程的启动进程的启动Android Framework层是运行在ART虚拟机之上的,对于一般的Java进程是不具备主动创建进程的能力的。我们都知道Android中存在四大组件:Activity、Service、BroadcastReceiver和ContentProvider,那么为什么这样划分呢,一个主要的原因是在四大组件的启动阶段,如果宿主进程没有正在运行,那么系统服务进程system_server将会先拉起进程,然后才会继续启动组件。简而言之,正因为AMS将安卓中进程的创建、销毁及优先级进行了封装,应用侧开发者才能够在对进程无感知的情况的同时使用四大组件。启动四大组件方法 startActivity, sendBroadcast, startService/bindService 和 getContentProviderImpl 之所以能够启动进程,是因为它们都会通过发送 binder 消息到 AMS 进行处理,当 AMS 发现对应组件没有在 xml 声明的进程启动时,会先拉起该进程,然后再启动对应组件。也就是说,四大组件正是APP进程的入口。它们拉起进程的方式都是一致的,基本流程:也就是说,四大组件正是APP进程的入口。Zygote进程启动,初始化虚拟机及基本环境,同时进入一个无限循环,提供创建 java 进程服务AMS 通过调用 () 方法,发送 socket 信息到 Zygote 进程Zygote 进程处理消息,并通过fork创建应用进程应用进程反射调用 方法,进入自身逻辑 (初始化 Looper/Binder 等主要服务 )AMS 创建进程成功后,会将进程以 ProcessRecord 的形式进行封装、管理。Zygote进程启动,初始化虚拟机及基本环境,同时进入一个无限循环,提供创建 java 进程服务AMS 通过调用 () 方法,发送 socket 信息到 Zygote 进程Zygote 进程处理消息,并通过fork创建应用进程应用进程反射调用 方法,进入自身逻辑 (初始化 Looper/Binder 等主要服务 )AMS 创建进程成功后,会将进程以 ProcessRecord 的形式进行封装、管理。彩蛋:实用的进程相关adb命令彩蛋:实用的进程相关adb命令Java进程的创建与销毁实时adb logcat -b events | grep proc**07-16 14:19:23.357 4774 4800 I am_proc_start: [0,30314,10063,,activity,/.StartActivity]07-16 14:19:23.375 4774 6027 I am_proc_bound: [0,30314,]07-16 14:19:31.621 4774 5281 I am_proc_died: [0,30314,,900,17]adb logcat -b events | grep proc**07-16 14:19:23.357 4774 4800 I am_proc_start: [0,30314,10063,,activity,/.StartActivity]07-16 14:19:23.375 4774 6027 I am_proc_bound: [0,30314,]07-16 14:19:31.621 4774 5281 I am_proc_died: [0,30314,,900,17]获取应用进程中组件详细信息adb shell dumpsys activity p <;packageName>;*APP* UID 10115 ProcessRecord{4114d9d 18987:/u0a115} user #0 uid=10115 gids={50115, 20115, 9997, 3002, 3003, 3001} requiredAbi=armeabi-v7a instructionSet=arm class= ... // adj, procState优先级信息 oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0 curSchedGroup=2 setSchedGroup=2 systemNoUi=false trimMemoryLevel=0 curProcState=2 repProcState=2 pssProcState=5 setProcState=2 ... **Activities**: - ActivityRecord{5e38d19 u0 /. t948} **Services**: - ServiceRecord{13f23bc u0 /} ... **Connections**: - ConnectionRecord{77ae579 u0 CR /:@30b4240} ... **Published Providers**: - ->; ContentProviderRecord{76d000a u0 /} ... **Connected Providers**: - c887614//.SettingsProvider->;18987:/u0a115 s1/1 u0/0 +19h23m3s147ms - c4d7fba//.MediaProvider->;18987:/u0a115 s0/1 u1/2 +1m10s935ms **Receivers**: - ReceiverList{4afbc5 18987 /10115/u0 remote:687d23c} ...adb shell dumpsys activity p <;packageName>;*APP* UID 10115 ProcessRecord{4114d9d 18987:/u0a115} user #0 uid=10115 gids={50115, 20115, 9997, 3002, 3003, 3001} requiredAbi=armeabi-v7a instructionSet=arm class= ... // adj, procState优先级信息 oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0 curSchedGroup=2 setSchedGroup=2 systemNoUi=false trimMemoryLevel=0 curProcState=2 repProcState=2 pssProcState=5 setProcState=2 ... **Activities**: - ActivityRecord{5e38d19 u0 /. t948} **Services**: - ServiceRecord{13f23bc u0 /} ... **Connections**: - ConnectionRecord{77ae579 u0 CR /:@30b4240} ... **Published Providers**: - ->; ContentProviderRecord{76d000a u0 /} ... **Connected Providers**: - c887614//.SettingsProvider->;18987:/u0a115 s1/1 u0/0 +19h23m3s147ms - c4d7fba//.MediaProvider->;18987:/u0a115 s0/1 u1/2 +1m10s935ms **Receivers**: - ReceiverList{4afbc5 18987 /10115/u0 remote:687d23c} ...获取应用优先级信息adb shell dumpsys activity oProc 0: fore T/A/TOP trm: 0 18987:/u0a115 (top-activity) oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0 state: cur=TOP set=TOP lastPss=268MB lastSwapPss=0.00 lastCachedPss=0.00 cached=false empty=false hasAboveClient=falseadb shell dumpsys activity oProc 0: fore T/A/TOP trm: 0 18987:/u0a115 (top-activity) oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0 state: cur=TOP set=TOP lastPss=268MB lastSwapPss=0.00 lastCachedPss=0.00 cached=false empty=false hasAboveClient=false进程的优先级进程的优先级进程的优先级Android Framework中进程优先级的衡量单位有两种,除了 adj (对应 lmk 的 oom_score_adj)之外,新添了 procState 变量。这两个优先级相辅相成,adj 更多的用在给 lmk 判断该进程是否应该被杀死,而procState 更多的给 Framework 层的服务给进程状态";定级";,例如,AMS可以简单粗暴的通过判断 procState 是否小于等于 PROCESS_STATE_IMPORTANT_FOREGROUND 来判断该进程是否为";前台进程";:[]@Overridepublic ;boolean ;isAppForeground(int ;uid) ;{ ; ; ; ;synchronized ;(this) ;{ ; ; ; ; ; ; ; ;UidRecord ;uidRec ;= ;(uid); ; ; ; ; ; ; ; ;if ;(uidRec ;== ;null ;|| ;) ;{ ; ; ; ; ; ; ; ; ; ; ; ;return ;false; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ;return ; ;<;= ;_STATE_IMPORTANT_FOREGROUND; ; ; ; ;}}@Overridepublic ;boolean ;isAppForeground(int ;uid) ;{ ; ; ; ;synchronized ;(this) ;{ ; ; ; ; ; ; ; ;UidRecord ;uidRec ;= ;(uid); ; ; ; ; ; ; ; ;if ;(uidRec ;== ;null ;|| ;) ;{ ; ; ; ; ; ; ; ; ; ; ; ;return ;false; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ;return ; ;<;= ;_STATE_IMPORTANT_FOREGROUND; ; ; ; ;}}这里的 UidRecord 是 Android 常用的权限管理方案,如果没有做修改的话,普通应用创建的进程都是在同一个 uid 里的。在系统侧,Android 常常通过 uid 来划分对应的进程是否具有相应的优先级。关于Android中adj与procState具体值的含义,可以查看文章最后的附录表格,具体场景仅供参考。如果需要细致判定当前进程优先级的状态,通过源码分析最为直观。adj、schedGroup、procState和adjType的核心计算步骤是在AMS中的computeOomAdjLocked方法完成的,如图:这个方法的核心执行无外乎以下几个功能:首先检查该进程是否处于高优场景中,如前台Activity、正在运行RemoteAnimation,正在处理广播和Service等该进程是否是某种特殊进程,如Home,height weight和backup是否存在进程因为service和content provider互相绑定提升优先级的情况如果都不是上述情况,处于的优先级都比较低,最低的是cache进程,AMS对系统整体cache进程个数有阈值限制,超过上限就会触发清理操作首先检查该进程是否处于高优场景中,如前台Activity、正在运行RemoteAnimation,正在处理广播和Service等高优场景该进程是否是某种特殊进程,如Home,height weight和backup特殊进程是否存在进程因为service和content provider互相绑定提升优先级的情况互相绑定如果都不是上述情况,处于的优先级都比较低,最低的是cache进程,AMS对系统整体cache进程个数有阈值限制,超过上限就会触发清理操作彩蛋:使用framework中的";自相矛盾";进行保活彩蛋:使用framework中的";自相矛盾";进行保活进程保活无外乎也是一种普通应用对操作系统的攻击手段,对于一般的攻击手段,我把它理解成使用开发者约定俗成的规则漏洞来突破普通用户原有权限的行为。比如说 buffer overflow,是利用了旧版本C编译器在切换函数堆栈时,没有有效检查堆栈信息作用范围的漏洞。使得普通应用用户可以利用超长的栈内信息覆盖调原有的堆栈跳转信息,使得应用执行其它意想不到的程序。通过这种方式可以获取到root权限;又比如说 TCP 劫持,是利用了发送方与接收方没有很好的 SEQ和ACK 序列的校验手段,使得中间者可以通过控制 SEQ和ACK的数值来控制正常通信方的流程。方式一:bindService 互相绑定以提升优先级方式一:bindService 互相绑定以提升优先级方式一:bindService 互相绑定以提升优先级这种优先级方式分为两种第一种,依赖高优先级 client:第一种,依赖高优先级 client:if ;(mayBeTop ;&& ;procState ;>; ;_STATE_TOP) ;{ ; ; ; ;switch ;(procState) ;{ ; ; ; ; ; ; ; ;case ;_STATE_BOUND_FOREGROUND_SERVICE: ; ; ; ; ; ; ; ;case ;_STATE_FOREGROUND_SERVICE: ; ; ; ; ; ; ; ; ; ; ; ;// ;Something ;else ;is ;keeping ;it ;at ;this ;level, ;just ;leave ;it. ; ; ; ; ; ; ; ; ; ; ; ;break; ; ; ; ; ; ; ; ;case ;_STATE_IMPORTANT_FOREGROUND: ; ; ; ; ; ; ; ;case ;_STATE_IMPORTANT_BACKGROUND: ; ; ; ; ; ; ; ;case ;_STATE_TRANSIENT_BACKGROUND: ; ; ; ; ; ; ; ;case ;_STATE_SERVICE: ; ; ; ; ; ; ; ; ; ; ; ;procState ;= ;_STATE_BOUND_FOREGROUND_SERVICE; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopType; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopSource; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopTarget; ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ;}}if ;(mayBeTop ;&& ;procState ;>; ;_STATE_TOP) ;{ ; ; ; ;switch ;(procState) ;{ ; ; ; ; ; ; ; ;case ;_STATE_BOUND_FOREGROUND_SERVICE: ; ; ; ; ; ; ; ;case ;_STATE_FOREGROUND_SERVICE: ; ; ; ; ; ; ; ; ; ; ; ;// ;Something ;else ;is ;keeping ;it ;at ;this ;level, ;just ;leave ;it. ; ; ; ; ; ; ; ; ; ; ; ;break; ; ; ; ; ; ; ; ;case ;_STATE_IMPORTANT_FOREGROUND: ; ; ; ; ; ; ; ;case ;_STATE_IMPORTANT_BACKGROUND: ; ; ; ; ; ; ; ;case ;_STATE_TRANSIENT_BACKGROUND: ; ; ; ; ; ; ; ;case ;_STATE_SERVICE: ; ; ; ; ; ; ; ; ; ; ; ;procState ;= ;_STATE_BOUND_FOREGROUND_SERVICE; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopType; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopSource; ; ; ; ; ; ; ; ; ; ; ; ; ;= ;mayBeTopTarget; ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ;}}maybeTop 为 true 需要 ContentProvider 或者 Service 的 client 正在前台显示 Activity同理,通过让用户选择该client来提供服务,例如WallPaperService,可以让system_server成为client,以此来提高进程优先级。第二种,两个进程互相绑定:第二种,两个进程互相绑定:if ;((&_FOREGROUND_SERVICE) ;!= ;0) ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_BOUND_FOREGROUND_SERVICE;} ;else ;if ;(mWakefulness ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;== ;_AWAKE ;&& ; ; ; ; ; ; ; ;(&_FOREGROUND_SERVICE_WHILE_AWAKE) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;!= ;0) ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_BOUND_FOREGROUND_SERVICE;} ;else ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_IMPORTANT_FOREGROUND;}...if ;(procState ;>; ;clientProcState) ;{ ; ; ; ;procState ;= ;clientProcState; ; ; ; ;if ;(adjType ;== ;null) ;{ ; ; ; ; ; ; ; ;adjType ;= ;";service";; ; ; ; ;}}if ;((&_FOREGROUND_SERVICE) ;!= ;0) ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_BOUND_FOREGROUND_SERVICE;} ;else ;if ;(mWakefulness ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;== ;_AWAKE ;&& ; ; ; ; ; ; ; ;(&_FOREGROUND_SERVICE_WHILE_AWAKE) ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;!= ;0) ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_BOUND_FOREGROUND_SERVICE;} ;else ;{ ; ; ; ;clientProcState ;= ; ; ; ; ; ; ; ; ; ; ; ;_STATE_IMPORTANT_FOREGROUND;}...if ;(procState ;>; ;clientProcState) ;{ ; ; ; ;procState ;= ;clientProcState; ; ; ; ;if ;(adjType ;== ;null) ;{ ; ; ; ; ; ; ; ;adjType ;= ;";service";; ; ; ; ;}}通过设置 flag,两个普通的进程可以通过互相";攀升";来提升优先级方式二、监听锁屏广播拉起Activity,监听解锁广播销毁Activity:方式二、监听锁屏广播拉起Activity,监听解锁广播销毁Activity:方式二、监听锁屏广播拉起Activity,监听解锁广播销毁Activity:具体步骤:启动一个Service,通过动态广播receiver接收锁屏、开屏广播灭屏时,启动Activity到前台开屏时,将Activity进行 finish,确保用户无感知启动一个Service,通过动态广播receiver接收锁屏、开屏广播灭屏时,启动Activity到前台开屏时,将Activity进行 finish,确保用户无感知adb shell ps | grep <;pacakgeName>;ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes) All known processes: *APP* UID 10064 ProcessRecord{f59eb2f 30917:/u0a64} ... oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100 curSchedGroup=1 setSchedGroup=1 systemNoUi=false trimMemoryLevel=0 curProcState=5 repProcState=5 pssProcState=5 setProcState=5 lastState1675486158=-23s716msadb shell ps | grep <;pacakgeName>;ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes) All known processes: *APP* UID 10064 ProcessRecord{f59eb2f 30917:/u0a64} ... oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100 curSchedGroup=1 setSchedGroup=1 systemNoUi=false trimMemoryLevel=0 curProcState=5 repProcState=5 pssProcState=5 setProcState=5 lastState1675486158=-23s716ms(该方法在 Android 8.0 上测试过仍有效,更高版本尚未测试;因为是利用了 service 与动态广播的特性,所以 framework 很难对这个逻辑做出应对,除非是在系统侧维护一个 service 黑名单)进程的清理进程的清理进程的清理虽然杀进程有这么多的花样,但常见的方式就三种:清理名称触发场景功能kill粒度最细,用于进程自杀、AMS 查杀单个缓存进程等杀死单个 java 进程killBackground普通应用也可以通过 AM 服务调用杀死系统中 background 进程force-stop以 package 为单位,强力杀死和该包有关联的进程并禁止大部分自启杀死该包下所有进程,关闭并销毁相关组件普通的查杀方式如kill和killBackground都只是杀死单个或部分进程,当进程死亡后,会因为 binder fd 的释放通过死亡回调通知 AMS 进程已死,这期间 AMS 也有可能因为 Service 等组件重新将进程拉起。考虑到拉活方案花样多,应用中的其它 java 进程或 c 进程仍然可以通过启动组件的方式重新将进程拉起来。在一般的原生机器上,force-stop虽然很少使用,一般只在设置里的";强制停止";按钮触发。除了杀死进程之外也会销毁组件等信息,同时也会更改 PMS 中对应包名的状态,避免再次拉活。其主要功能如下:彩蛋:当我们上滑应用卡片时Android在做什么彩蛋:当我们上滑应用卡片时Android在做什么systemui 进程中的 /. 接收到卡片滑动事件systemui 获取到 AMS 服务,再调用 方法来移除 Task 和杀死显示该界面的进程;注意这个方法普通应用是没有调用权限的。最后通过 AMS 的 cleanUpRemovedTaskLocked 方法来杀死进程,这个方法的具体实现如下:systemui 进程中的 /. 接收到卡片滑动事件systemui 获取到 AMS 服务,再调用 方法来移除 Task 和杀死显示该界面的进程;注意这个方法普通应用是没有调用权限的。最后通过 AMS 的 cleanUpRemovedTaskLocked 方法来杀死进程,这个方法的具体实现如下:void ;cleanUpRemovedTaskLocked(TaskRecord ;tr, ;boolean ;killProcess, ;boolean ;removeFromRecents) ;{ ; ; ; ;// ;1. ;在最近任务中移除 ;Task ; ; ; ;if ;(removeFromRecents) ;{ ; ; ; ; ; ; ; ;(tr); ; ; ; ;} ; ; ; ;... ; ; ; ;// ;2. ;选择需要查杀的进程 ; ; ; ;final ;String ;pkg ;= ;(); ; ; ; ;ArrayList<;ProcessRecord>; ;procsToKill ;= ;new ;ArrayList<;>;(); ; ; ; ;ArrayMap<;String, ;SparseArray<;ProcessRecord>;>; ;pmap ;= ;(); ; ; ; ;for ;(int ;i ;= ;0; ;i ;<; ;(); ;i++) ;{ ; ; ; ; ; ; ; ;SparseArray<;ProcessRecord>; ;uids ;= ;(i); ; ; ; ; ; ; ; ;for ;(int ;j ;= ;0; ;j ;<; ;(); ;j++) ;{ ; ; ; ; ; ; ; ; ; ; ; ;ProcessRecord ;proc ;= ;(j); ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ; ; ; ; ; ; ; ; ;// ;2.1 ;如果 ;Task ;所在进程还有别的 ;Task ;在最近任务中显示,那么该进程不会被杀 ; ; ; ; ; ; ; ; ; ; ; ;for ;(int ;k ;= ;0; ;k ;<; ;(); ;k++) ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;TaskRecord ;otherTask ;= ;(k).getTask(); ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;if ;( ;!= ; ;&& ;) ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;return; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;// ;2.2 ;进程有前台service的不会被杀,典型的有音乐播放软件 ; ; ; ; ; ; ; ; ; ; ; ;if ;() ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;return; ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;// ;Add ;process ;to ;kill ;list. ; ; ; ; ; ; ; ; ; ; ; ;(proc); ; ; ; ; ; ; ; ;} ; ; ; ;} ; ; ; ;// ;3. ;正式查杀 ; ; ; ;for ;(int ;i ;= ;0; ;i ;<; ;(); ;i++) ;{ ; ; ; ; ; ; ; ;ProcessRecord ;pr ;= ;(i); ; ; ; ; ; ; ; ;// ;如果满足这两个条件才会立即被杀 ; ; ; ; ; ; ; ;if ;( ;== ;_GROUP_BACKGROUND ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;&& ;()) ;{ ; ; ; ; ; ; ; ; ; ; ; ;(";remove ;task";, ;true); ; ; ; ; ; ; ; ;} ;else ;{ ; ; ; ; ; ; ; ; ; ; ; ; ;= ;";remove ;task";; ; ; ; ; ; ; ; ;} ; ; ; ;}}void ;cleanUpRemovedTaskLocked(TaskRecord ;tr, ;boolean ;killProcess, ;boolean ;removeFromRecents) ;{ ; ; ; ;// ;1. ;在最近任务中移除 ;Task ; ; ; ;if ;(removeFromRecents) ;{ ; ; ; ; ; ; ; ;(tr); ; ; ; ;} ; ; ; ;... ; ; ; ;// ;2. ;选择需要查杀的进程 ; ; ; ;final ;String ;pkg ;= ;(); ; ; ; ;ArrayList<;ProcessRecord>; ;procsToKill ;= ;new ;ArrayList<;>;(); ; ; ; ;ArrayMap<;String, ;SparseArray<;ProcessRecord>;>; ;pmap ;= ;(); ; ; ; ;for ;(int ;i ;= ;0; ;i ;<; ;(); ;i++) ;{ ; ; ; ; ; ; ; ;SparseArray<;ProcessRecord>; ;uids ;= ;(i); ; ; ; ; ; ; ; ;for ;(int ;j ;= ;0; ;j ;<; ;(); ;j++) ;{ ; ; ; ; ; ; ; ; ; ; ; ;ProcessRecord ;proc ;= ;(j); ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ; ; ; ; ; ; ; ; ;// ;2.1 ;如果 ;Task ;所在进程还有别的 ;Task ;在最近任务中显示,那么该进程不会被杀 ; ; ; ; ; ; ; ; ; ; ; ;for ;(int ;k ;= ;0; ;k ;<; ;(); ;k++) ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;TaskRecord ;otherTask ;= ;(k).getTask(); ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;if ;( ;!= ; ;&& ;) ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;return; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;// ;2.2 ;进程有前台service的不会被杀,典型的有音乐播放软件 ; ; ; ; ; ; ; ; ; ; ; ;if ;() ;{ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;return; ; ; ; ; ; ; ; ; ; ; ; ;} ; ; ; ; ; ; ; ; ; ; ; ;// ;Add ;process ;to ;kill ;list. ; ; ; ; ; ; ; ; ; ; ; ;(proc); ; ; ; ; ; ; ; ;} ; ; ; ;} ; ; ; ;// ;3. ;正式查杀 ; ; ; ;for ;(int ;i ;= ;0; ;i ;<; ;(); ;i++) ;{ ; ; ; ; ; ; ; ;ProcessRecord ;pr ;= ;(i); ; ; ; ; ; ; ; ;// ;如果满足这两个条件才会立即被杀 ; ; ; ; ; ; ; ;if ;( ;== ;_GROUP_BACKGROUND ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;&& ;()) ;{ ; ; ; ; ; ; ; ; ; ; ; ;(";remove ;task";, ;true); ; ; ; ; ; ; ; ;} ;else ;{ ; ; ; ; ; ; ; ; ; ; ; ; ;= ;";remove ;task";; ; ; ; ; ; ; ; ;} ; ; ; ;}}彩蛋:反保活的终结者彩蛋:反保活的终结者Android 中的进程查杀最强武器是force-stop,本质上它会通过遍历并杀死所有和应用有关的Java进程:force-stopprivate ;final ;boolean ;killPackageProcessesLocked(String ;packageName, ;int ;appId, ; ; ; ; ; ; ; ;int ;userId, ;int ;minOomAdj, ;boolean ;callerWillRestart, ;boolean ;allowRestart, ;boolean ;doit, ;boolean ;evenPersistent, ;String ;reason) ;{ ; ; ; ;ArrayList<;ProcessRecord>; ;procs ;= ;new ;ArrayList<;>;(); ; ; ; ;final ;int ;NP ;= ;().size(); ; ; ; ;for ;(int ;ip=0; ;ip<;NP; ;ip++) ;{ ; ; ; ; ; ; ; ;SparseArray<;ProcessRecord>; ;apps ;= ;().valueAt(ip); ; ; ; ; ; ; ; ;final ;int ;NA ;= ;(); ; ; ; ; ; ; ; ;for ;(int ;ia=0; ;ia<;NA; ;ia++) ;{ ; ; ; ; ; ; ; ; ; ; ; ;ProcessRecord ;app ;= ;(ia); ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ; ; ; ; ; ; ; ; ;// ;continue ;if ;the ;process ;do ;not ;need ;to ;kill ; ; ; ; ; ; ; ; ; ; ; ; ;= ;true; ; ; ; ; ; ; ; ; ; ; ; ;(app); ; ; ; ; ; ; ; ;} ; ; ; ;} ; ; ; ;int ;N ;= ;(); ; ; ; ;// ;force-stop ;的本质是通过遍历所有与应用有关的进程,依次查杀来实现杀死所有进程的 ; ; ; ;for ;(int ;i=0; ;i<;N; ;i++) ;{ ; ; ; ; ; ; ; ;removeProcessLocked((i), ;callerWillRestart, ;allowRestart, ;reason); ; ; ; ;} ; ; ; ;updateOomAdjLocked(); ; ; ; ;return ;N ;>; ;0;}private ;final ;boolean ;killPackageProcessesLocked(String ;packageName, ;int ;appId, ; ; ; ; ; ; ; ;int ;userId, ;int ;minOomAdj, ;boolean ;callerWillRestart, ;boolean ;allowRestart, ;boolean ;doit, ;boolean ;evenPersistent, ;String ;reason) ;{ ; ; ; ;ArrayList<;ProcessRecord>; ;procs ;= ;new ;ArrayList<;>;(); ; ; ; ;final ;int ;NP ;= ;().size(); ; ; ; ;for ;(int ;ip=0; ;ip<;NP; ;ip++) ;{ ; ; ; ; ; ; ; ;SparseArray<;ProcessRecord>; ;apps ;= ;().valueAt(ip); ; ; ; ; ; ; ; ;final ;int ;NA ;= ;(); ; ; ; ; ; ; ; ;for ;(int ;ia=0; ;ia<;NA; ;ia++) ;{ ; ; ; ; ; ; ; ; ; ; ; ;ProcessRecord ;app ;= ;(ia); ; ; ; ; ; ; ; ; ; ; ; ;... ; ; ; ; ; ; ; ; ; ; ; ;// ;continue ;if ;the ;process ;do ;not ;need ;to ;kill ; ; ; ; ; ; ; ; ; ; ; ; ;= ;true; ; ; ; ; ; ; ; ; ; ; ; ;(app); ; ; ; ; ; ; ; ;} ; ; ; ;} ; ; ; ;int ;N ;= ;(); ; ; ; ;// ;force-stop ;的本质是通过遍历所有与应用有关的进程,依次查杀来实现杀死所有进程的 ; ; ; ;for ;(int ;i=0; ;i<;N; ;i++) ;{ ; ; ; ; ; ; ; ;removeProcessLocked((i), ;callerWillRestart, ;allowRestart, ;reason); ; ; ; ;} ; ; ; ;updateOomAdjLocked(); ; ; ; ;return ;N ;>; ;0;}想要做反保活的话,我们只需要在 removeProcessLocked 的遍历之前,将 java 进程和在其同一cgroup的c进程一起通过发送信号hang住,再通过循环依次杀死所有进程,这种方法基本能杜绝所有拉活方案。总结总结总结进程管理与大家日常开发息息相关,也是在Android系统中是个举足轻重的模块。相信通过本系列的两篇文章,大家已经对进程启动期间涉及到fork、对进程的优先级管理涉及到adj、对进程的调度这些概念已经有了更加深入的理解了。二、苹果M1优化的macOS Big Sur将于11月12日到货
苹果于6月在WWDC上宣布了macOS Big Sur,尽管我们已于9月通过公开测试版看到了预览,但该软件尚未正式推出。在今天针对Mac的活动中,该公司推出了其基于ARM的新型笔记本电脑芯片组:M1。它还共享了对新芯片的一些其他优化以及软件更新的正式发布日期,该更新将于11月12日发布。苹果软件工程负责人克雷格·费德里希(Craig Federighi)在今天的演讲中说:“这是有史以来第一次,我们能够为自己的芯片设计macOS。”“ MacOS Big Sur经过精心设计,可以充分利用M1的所有功能和功能。”作为回顾,Big Sur带来了一些值得注意的更新,例如,经过改进的可自定义的控制中心,重新组织的通知中心以及对地图,Safari和消息的改进。苹果今天表示,该软件还经过调整,可以在该公司的新M1芯片上正常运行。与其他基于ARM的PC一样,苹果表示使用M1芯片组的Mac也将很快从睡眠中唤醒。启用M1的计算机上的MacOS Big Sur还将为其他特定的任务使用正确的内核,例如其他现代的基于ARM的设备-例如,高性能内核用于负担更多应用程序,而高效内核则用于强度较低的功能。Federighi说,在M1机器上,Safari运行Javascript程序的速度提高了一半半,响应速度几乎是以前的两倍。他说,动画也将快速流畅,渲染3D动画或编辑原始视频素材也将同样快速。他补充说,这部分归功于新的统一内存架构。“我们在Apple Silicon上构建了macOS,以将相同的数据格式用于视频解码,GPU和显示等内容,”因此,编辑人员无需浪费时间和金钱来转换文件。“当然,我们已经针对M1优化了所有应用程序,” Federighi说,他们大声喊了Pages,Numbers,Keynote,Garage Band,iMovie,Logic Pro和Final Cut Pro。困扰基于ARM的PC的最大问题之一是应用程序兼容性,苹果公司还指出其通用应用程序将在支持M1的设备上运行。该公司表示,Adobe和Omni Group即将推出其应用程序的通用版本,从下个月的Lightroom和明年年初的Photoshop开始。在活动期间,苹果公司还向众多开发人员炫耀,谈论将其应用程序转换为通用版本是多么容易。这种对于为新机器制造兼容应用程序的容易程度的认识是苹果成功转移到基于ARM的笔记本电脑的关键。微软在这一领域的失败是一个值得学习的明确教训。尚未移植到通用版本的现有应用程序将对Big Sur的Rosetta 2有所帮助。它将翻译为x64-86机器制作的应用程序,以便在Apple Silicon上运行。这听起来与Microsoft在Snapdragon PC上的仿真器相似,并且为开发人员提供了一些时间来将其应用程序迁移到通用平台。苹果在其开发人员页面上说,罗塞塔“不能替代创建应用程序的本机版本。”我们尚不知道《罗塞塔2》将持续多久。从我们已经看到的内容来看,Big Sur还具有重新设计的功能,尽管从我们的预览中看,更改是微妙的,感觉不像是改头换面,而更像是修饰。有了Metal的支持,一些增强功能已经浮出水面,例如,照片动画的显示速度更快。其他只有在使用新的自定义选项时才显而易见。现在我们已经确定了最终软件的正式发布日期,我们可以期待测试macOS更新-希望在其中一款采用M1的新Mac上进行。三、存款利率上限优化,降低存款利率
存款利率上限优化这个问题,降低存款利率1存款利率自律上限是指银行在贷款和存款利率方面的自律性约束,即存款利率上限。2因为在市场经济的条件下,银行的贷款和存款利率会受到市场供求关系和竞争压力的影响,为了维护金融市场的稳定性,保持金融秩序的良好发展,银行需要遵守国家有关存款利率自律上限的要求,确保银行业发展的稳定性,防止金融风险的发生。3存款利率自律上限的设定,对于保证金融市场的健康稳定发展以及促进金融业务的健康竞争至关重要,同时也对广大的储户和贷款人的利益具有重要的影响。存款利率自律上限是指商业银行自愿遵守的一种利率自律管理制度。根据中国银行业协会的制度要求,商业银行应当在规定的存款利率上下浮动范围内自主定价。存款利率自律上限就是商业银行在实行存款利率自主定价时,不能超过规定的最高利率的管理制度。存款利率自律上限的作用是防止银行过高地提高存款利率,导致资金成本过高,妨碍货币政策的实施和金融市场的稳定。存款利率上浮上限是指银行在存款利率上浮时,所能涨幅的最高上限。根据中国央行的规定,各类存款利率上浮上限不得超过存款基准利率的110%,其中大额存单的利率上浮上限为存款基准利率的130%。这一规定是为了保障存款人的权益,防止银行在存款利率上浮时出现过高的涨幅,从而保持银行体系的稳定。上一篇:湖南天气怎么样