ActivityManagerService原理分析

2024-04-19 16:18

本文主要是介绍ActivityManagerService原理分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.概述

ActivityManagerService是Framework层的核心服务之一,ActivityManagerService是Binder的子类,它的功能主要以下三点:

  • 四大组件的统一调度
  • 进程管理
  • 内存管理

二.ActivityManagerService中的重要变量

  • static final int MAX_ACTIVITYS =20;系统允许的最大后台activity的数目
  • static final int MAX_RECENT_TASK=20; 系统最多存储20个任务栈
  • static final int MAX_HIDDEN_APP=15;系统允许处于hidden状态的进程数目的最大值,超过这个值后,Ams会杀死掉优先级较低的进程
  • ActivityStackSupervisor mStackSupervisor; 通过这个类管理ActivityStacks
  • final ActiveServices mServices; 服务的管理类,管理服务的所有的逻辑
  • final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2]; 前台/后台广播队列
  • private final RecentTasks mRecentTasks; 最近的任务的意图列表
  • final ProcessMap mProcessNames = new ProcessMap(); 当前正在运行的所有进程列表
  • final ArrayList mLruProcesses = new ArrayList();最近使用的进程列表
  • final ArrayList mProcessesToGc = new ArrayList();一旦事情闲置,应该gc的进程列表
  • final HashMap

三.ActivityManagerService的启动过程

ActivityManagerService的启动是在systemserver进程的startBootstrapServices方法中启动的.下面通过源码来分析这个启动过程.
step1.systemserver.startBootstrapServices

private void startBootstrapServices() {// Activity manager runs the show.mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);
}

这里调用mSystemServiceManager.startService()来帮助处理,不过这里启动的是ActivityManagerService.Lifecycle类

setp2.SystemService startService

 public SystemService startService(String className) {final Class<SystemService> serviceClass;try {
//通过类加载将类加载进内存serviceClass = (Class<SystemService>)Class.forName(className);} catch (ClassNotFoundException ex) {}//调用startService(serviceClass)进一步处理return startService(serviceClass);}public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();final T service;try {//通过反射创建serviceConstructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} // Register it.mServices.add(service);// Start it.try {启动serviceservice.onStart();} catch (RuntimeException ex) {}return service;} }

因为这里启动的是ActivityManagerService.Lifecycle类,调用ActivityManagerService.Lifecycle类的start方法来启动,下面就看看这个类.
step3.ActivityManagerService.Lifecycle

 public static final class Lifecycle extends SystemService {private final ActivityManagerService mService;public Lifecycle(Context context) {super(context);
这个类创建对象的同时就创建出了ActivityManagerServicemService = new ActivityManagerService(context);}@Overridepublic void onStart() {//启动ActivityManagerServicemService.start();}public ActivityManagerService getService() {return mService;}}

从上面的代码可以看出,这个类实际上就是帮我们创建出ActivityManagerService的对象,并且调用start方法开启服务.下面在看看ActivityManagerService在创建的时候做了什么.

step4.ActivityManagerService的构造方法

public ActivityManagerService(Context systemContext) {mContext = systemContext;mFactoryTest = FactoryTest.getMode();mSystemThread = ActivityThread.currentActivityThread();Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());mHandlerThread = new ServiceThread(TAG,android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);mHandlerThread.start();//创建处理主要逻辑的handermHandler = new MainHandler(mHandlerThread.getLooper());//创建处理UI的handler,比如处理无响应的对话框,弹出debug模式的对话框mUiHandler = new UiHandler();//创建存放前台和后台广播的广播队列mFgBroadcastQueue = new BroadcastQueue(this, mHandler,"foreground", BROADCAST_FG_TIMEOUT, false);mBgBroadcastQueue = new BroadcastQueue(this, mHandler,"background", BROADCAST_BG_TIMEOUT, true);mBroadcastQueues[0] = mFgBroadcastQueue;mBroadcastQueues[1] = mBgBroadcastQueue;//创建管理service的类mServices = new ActiveServices(this);//创建管理provider的类mProviderMap = new ProviderMap(this);在ams服务之外创建电池统计服务// TODO: Move creation of battery stats service outside of activity manager service.//创建system目录File dataDir = Environment.getDataDirectory();File systemDir = new File(dataDir, "system");systemDir.mkdirs();//创建电池服务mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);mBatteryStatsService.getActiveStatistics().readLocked();mBatteryStatsService.scheduleWriteToDisk();mOnBattery = DEBUG_POWER ? true: mBatteryStatsService.getActiveStatistics().getIsOnBattery();mBatteryStatsService.getActiveStatistics().setCallback(this);//创建跟踪长期执行流程以寻找滥用等糟糕的应用行为的服务mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));//创建关于和控制应用程序操作的信息的服务mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));// User 0 is the first and only user that runs at boot.//UserHandle表示一个用户mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));mUserLru.add(UserHandle.USER_OWNER);updateStartedUserArrayLocked();GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",ConfigurationInfo.GL_ES_VERSION_UNDEFINED);mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));//配置信息mConfiguration.setToDefaults();mConfiguration.setLocale(Locale.getDefault());mConfigurationSeq = mConfiguration.seq = 1;mProcessCpuTracker.init();//用户要求以屏幕尺寸兼容模式运行的软件包mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);//用于启动最近的任务的意图列表mRecentTasks = new RecentTasks(this);//管理Activity的类,通过这个运行所有的ActivityStack,辅助启动startactivitymStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);//重新启动时保存最近的任务信息mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);//运行时cpu用于收集线程mProcessCpuThread = new Thread("CpuTracker") {@Overridepublic void run() {while (true) {try {try {synchronized(this) {final long now = SystemClock.uptimeMillis();long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;//Slog.i(TAG, "Cpu delay=" + nextCpuDelay//        + ", write delay=" + nextWriteDelay);if (nextWriteDelay < nextCpuDelay) {nextCpuDelay = nextWriteDelay;}if (nextCpuDelay > 0) {mProcessCpuMutexFree.set(true);this.wait(nextCpuDelay);}}} catch (InterruptedException e) {}updateCpuStatsNow();} catch (Exception e) {Slog.e(TAG, "Unexpected exception collecting process stats", e);}}}};//获取看门狗对象,并且将当前线程也就是这个服务添加进去Watchdog.getInstance().addMonitor(this);Watchdog.getInstance().addThread(mHandler);}

acitivtymanagerservie的构造函数主要初始化了四大组件的管理类,以及处理主要逻辑的mHandler和处理ui相关的mUiHandler ,比如弹出anr等对话框.

Step5.ActivityManagerService.start()

   private void start() {
//删除所有的进程组,确保刚启动的时候是没有进程的Process.removeAllProcessGroups();将CPU用来收集线程的线程启动mProcessCpuThread.start();
启动电池服务mBatteryStatsService.publish(mContext);
启动关于和控制应用程序操作的信息的服务mAppOpsService.publish(mContext);类似servermanger,只不过这个是用于当前进程LocalServices.addService(ActivityManagerInternal.class, new LocalService());}

到这一步ActivityManagerService服务就真正的开启了,就会开始真正的执行前面说的3个主要功能了.

四.主要功能之一的四大组件的统一调度

ActivityManagerService最主要的功能就是统一的管理者activity,service,broadcast,provider的创建,运行,关闭.我们在应用程序中启动acitivity,关闭acitiviy等操作最终都是要通过ams来统一管理的.这个过程非常的复杂,不是一下子可以讲的清楚的,我这里推荐老罗的博客来讲解四大组件的启动过程:

  • Android应用程序内部启动Activity过程(startActivity)的源代码分析
  • Android系统在新进程中启动自定义服务过程(startService)的原理分析
  • Android应用程序注册广播接收器(registerReceiver)的过程分析
  • Android应用程序发送广播(sendBroadcast)的过程分析
  • Android应用程序组件Content Provider简要介绍和学习计划

五.主要功能之一的内存管理

我们知道当一个进程中的acitiviy全部都关闭以后,这个空进程并不会立即就被杀死.而是要等到系统内存不够时才会杀死.但是实际上ActivityManagerService并不能够管理内存,android的内存管理是Linux内核中的内存管理模块和OOM进程一起管理的.Android进程在运行的时候,会通过Ams把每一个应用程序的oom_adj值告诉OOM进程,这个值的范围在-16-15,值越低说明越重要,越不会被杀死.当发生内存低的时候,Linux内核内存管理模块会通知OOm进程根据AMs提供的优先级强制退出值较高的进程.因此Ams在内存管理中只是扮演着一个提供进程oom_adj值的功能.真正的内存管理还是要调用OOM进程来完成.下面通过调用Activity的finish()方法来看看内存释放的情况.

当我们手动调用finish()方法或者按back键时都是会关闭activity的,,在调用finish的时候只是会先调用ams的finishActivityLocked方法将当前要关闭的acitiviy的finish状态设置为true,然后就会先去启动新的acitiviy,当新的acitiviy启动完成以后就会通过消息机制通知Ams,Ams在调用activityIdleInternalLocked方法来关闭之前的acitiviy.下面就看看activityIdleInternalLocked的源码

ActivityStackSupevis.activityIdleInternalLocked

 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,Configuration config) {//所有要暂停的activityArrayList<ActivityRecord> stops = null;//所有要finish的activityArrayList<ActivityRecord> finishes = null;ArrayList<UserState> startingUsers = null;int NS = 0;int NF = 0;boolean booting = false;boolean activityRemoved = false;if (allResumedActivitiesIdle()) {if (r != null) {
1.通知所有需要内存回收的进程进行内存回收(这些进程都保存在mProgressToGc列表中)mService.scheduleAppGcsLocked();}2.  分别拿到所有要stop和finish的activity存放在stops和finishs容器中,然后将记录清空stops = processStoppingActivitiesLocked(true);NS = stops != null ? stops.size() : 0;if ((NF = mFinishingActivities.size()) > 0) {finishes = new ArrayList<>(mFinishingActivities);mFinishingActivities.clear();}if (mStartingUsers.size() > 0) {startingUsers = new ArrayList<>(mStartingUsers);mStartingUsers.clear();}3. 停止stops中的所有activityfor (int i = 0; i < NS; i++) {r = stops.get(i);final ActivityStack stack = r.task.stack;if (stack != null) {if (r.finishing) {stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);} else {stack.stopActivityLocked(r);}}}4. 销毁finishs中的所有activityfor (int i = 0; i < NF; i++) {r = finishes.get(i);final ActivityStack stack = r.task.stack;if (stack != null) {activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");}}5.该步骤内部真正地进行内存回收工作,包括杀死不必要的进程
mService.trimApplications();return r;}

在这个方法中除了第一步通知客户进程调用GC来主动回收内存以外,剩下的步骤都是没有操作到内存的,所以说stop或者destroy的回调方法调用的时候只是一个状态的变化,而没有真正意义的对内存进行实质性的停止或者销毁.但是会调用trimApplications方法来进一步操作.

ActivityManagerService.trimApplications

final void trimApplications() {synchronized (this) {int i;首先删除mRemoveProcess列表中包含的进程.这里一般包含的是crash后的进程,弹出ANR的进程,调用KillBackGroundProgress()方法杀死的进程.也就是说crash或者弹出Anr对话框我们点确定的时候系统并不会立马就将这些进程杀死,而是要等空闲时调用activityIdleInternalLocked方法时才会真正的来杀死.for (i=mRemovedProcesses.size()-1; i>=0; i--) {final ProcessRecord app = mRemovedProcesses.get(i);if (app.activities.size() == 0&& app.curReceiver == null && app.services.size() == 0) {if (app.pid > 0 && app.pid != MY_PID) {不杀死当前进程app.kill("empty", false);} else {try {app.thread.scheduleExit();} catch (Exception e) {// Ignore exceptions.}}cleanUpApplicationRecordLocked(app, false, true, -1);
将杀死的进程,移除mRemovedProcesses.remove(i);if (app.persistent) {addAppLocked(app.info, false, null /* ABI override */);}}}// Now update the oom adj for all processes.
告诉OOM Killer所有进程的优先级updateOomAdjLocked();}}

通过上面的源码知道,我们调用finish方法时关闭一个acitiviy的时候并不会真正的在内存中销毁它,而只是会调用onDestroy方法而已.除了会杀死mRemoveProcess列表中的进程,另外也就只会告诉OOM Killer所有进程的优先级.并不会主动的去杀死其他进程.

这篇关于ActivityManagerService原理分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918038

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

MySQL中的MVCC底层原理解读

《MySQL中的MVCC底层原理解读》本文详细介绍了MySQL中的多版本并发控制(MVCC)机制,包括版本链、ReadView以及在不同事务隔离级别下MVCC的工作原理,通过一个具体的示例演示了在可重... 目录简介ReadView版本链演示过程总结简介MVCC(Multi-Version Concurr

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专