面试官:讲讲你对Activity启动机制的理解。。

简介: 笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如<mark>RxJava</mark>,<mark>OkHttp</mark>,<mark>Retrofit</mark>,以及后来谷歌推出的<mark>协程</mark>等,都只在使用层面,对于他们<mark>内部原理</mark>,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自

前言

本文主要记录笔者对Android系统启动流程的一个的一个过程了解

笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如RxJava,OkHttp,Retrofit,以及后来谷歌推出的协程等,都只在使用层面,对于他们内部原理,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己还是什么都不会,过一段时间可能就忘记了

  • 为了能更加深刻的理解这些机制,笔者决定自己深入Framework层面去考察下这些代码的机制:

讲解时间线如下:

对于源码解析部分,可能大家会有部分疑惑,我们列出部分:

  • 1.zygoye是什么?有什么作用

    答:zygote英文翻译是“孵化”。

在了解zygote之前首先我们需要知道我们进程是如何创建的?

我们安卓设备内核使用的是linux内核,
开机先是启动一个init进程,在init进程中会创建一个zygote进程,
zygote进程会启动java虚拟机并注册java-native 的jni方法,通过jni调用到java层的ZygoteInit,在这个类里面会注册一个ServerSocket用于设备创建应用进程的需要。
当启动一个应用需要创建一个进程时,会调用到这个ServerSocket的创建进程流程,主要是通过fork的方式创建进程,这样子进程就拥有了父进程所有的资源,
fork会返回两次,当返回的pid=0时说明现在是处于子进程,继续处理子进程流程就可以了。如果是SystemServer进程,则会启动各类服务,包括AMS,WMS等系统服务。

按上面所讲,zygote就是作为创建子进程的一个孵化器。

  • 2.SystemServer是什么?有什么作用?它与zygote的关系是什么?

答:SystemServer是一个由zygotefork出来的子进程,该进程主要作用是创建创建binder线程池和启动android运行需要的诸多系统服务,比如:AMS,PMS,WMS等并启动系统Launcher

  • 3.ActivityManagerService是什么?什么时候初始化的?有什么作用?

答:ActivityManagerService,简称AMS,服务端对象,负责统一调度系统中四大组件的生命周期。ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService

**APP和AMS其实是通过binder进行通讯的。**

binder机制简述。
    binder其实是进程间通信的一种方式,在linux进程中有socket,管道,共享内存,消息队列等方式,
    而由于binder对性能消耗低和安全性方面的考虑,android大量的使用了binder通讯 ,可以说binder是android的基石。
binder模型简述:
    首先我们binder是通过CS架构进行设计的:Client和Service
    先搞懂三个概念:client,server和serverManger
    server通过binder通讯将自己注册到serverManager中,client通过binder获取serverManager中注册的server,
    其实是获取一个handle,通过这个handle就可以在bidner驱动中找找到server进程和需要处理的方法地址等信息。
    从而间接实现了进程间通讯,这个是binder的一个简要概述,详细的需要去了解binder驱动实现原理。
  • 4.Launcher是什么?什么时候启动的?

    答:Launcher也是一个应用app,是在SystemServer启动的时候,启动的一个应用
    
  • 5.Instrumentation是什么?和ActivityThread是什么关系?

    答:Instrumentation是一个沟通Activity和AMS以及ActivityThread和Activity中间桥梁工具类
    例如:Activity.startActivity

        ->mInstrumentation.execStartActivity
        ->ActivityManagerService.startActivity->ActivityThread.thread.scheduleLaunchActivity
        ->ActivityThread.handleLaunchActivity
        ->mInstrumentation.callActivityOnCreate
    

针对以上问题:笔者会以源码的方式呈现

前面文章我们已经介绍过了:

Android系统启动-zygote进程详解:

android体系课-系统启动流程-之zygote进程启动过程源码分析

和Android系统启动-SystemServer启动过程详解:

android体系课-系统启动流程-之SystemServer启动过程源码分析

今天这篇文章我们来介绍下Activity的启动过程

startActivity分为根Activity和普通Activity

1.根Activity即应用启动的第一个Activity:

应用根Activity的启动过程:

根据之前对startActivity启动流程的分析,在ActivityStackSupervisor.startSpecificActivityLocked(next, true, true);方法中:
对是否创建进程进行判断:
1.如果有创建(针对普通Activity):则直接调用realStartActivityLocked(activity, app, top == activity, true),这个就是普通Activity的启动流程
2.没有创建(针对根Activity  ):则调用AMS的startProcessLocked:

1.要启动一个应用APP,需要先创建一个应用程序进程,这个创建过程是MS给孵化进程发送的创建进程的请求fork

    AMS:
    startProcessLocked:
        //获取要创建的进程的用户uid
        int uid = app.uid;
        //对gid创建和赋值
        if (ArrayUtils.isEmpty(permGids)) {
            gids = new int[3];
        } else {
            gids = new int[permGids.length + 3];
            System.arraycopy(permGids, 0, gids, 3, permGids.length);
        }
        gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
        gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
        gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
        //设置待启动的类名
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        //启动进程
        startResult = Process.start(entryPoint,...)
            zygoteProcess.start(processClass...)
                startViaZygote(processClass...)
                    zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
                        分析1:openZygoteSocketIfNeeded://如果没有打开孵化进程的socket通讯,那就尝试打开,如果已经打开,那就什么都不做,可能会阻塞并多次尝试连接
                                    primaryZygoteState = ZygoteState.connect(mSocket);//与孵化进程建立连接
                                        zygoteSocket.connect(new LocalSocketAddress(socketAddress,LocalSocketAddress.Namespace.RESERVED));//连接
                                            zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());//获取InputStream
                                            zygoteWriter = new BufferedWriter(new OutputStreamWriter(zygoteSocket.getOutputStream()), 256);//获取OutPutStream
                                            return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter..)//返回一个ZygoteState里面包含了输入和输出流
                        分析2:zygoteSendArgsAndGetResult(new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter..),args)
                                    writer.write(Integer.toString(args.size()));//给socket写数据
                                    result.pid = inputStream.readInt();//从socket中读数据
                                    result.usingWrapper = inputStream.readBoolean();
                                    return result; result = Process.ProcessStartResult();//此处已经表明应用进程启动成功
                                    //之后会从fork处启动应用程序进程:进程类为:"android.app.ActivityThread" 方法为main,这个时候就正式进入应用程序的main方法中
                                    
        
2.android.app.ActivityThread   main方法    
    ActivityThread.main{
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
            //调用AMS的attachApplication
            mgr.attachApplication(mAppThread);
                attachApplicationLocked(thread, callingPid);
                    //获取之前创建的ProcessRecord
                    app = mPidsSelfLocked.get(pid);
                    //回调到ActivityThread的ApplicationThread中
                    thread.bindApplication(processName, appInfo, providers...)
                    //1.包含创建Application,调用application的onCreate方法等
                    mStackSupervisor.attachApplicationLocked(app)
                        //内部又调用到了realStartActivityLocked方法,这个方法之前分析过就是启动Activity的方式
                        realStartActivityLocked(hr, app, true, true)
    
    }

总结:根Activity是在调用realStartActivityLocked真正启动Activity之前,判断进程是否存在,如果存在,则直接调用realStartActivityLocked
如果不存在则会调用startProcessLocked方法去创建应用进程,进程创建成功后,会启动ActivityThread的main方法
这个方法内部调用了attach方法,这个方法调用到AMS的内部,获取内部的ProcessRecord,通过bindApplication通知应用进程发起应用的创建createApplication,创建后回到AMS,AMS
调用realStartActivityLocked这里才是真正的根Activity启动的地方

根Activity创建的过程中涉及的进程
    Launcher进程桌面点击icon
    ---->AMS启动Activity前发现应用进程未启动
    --->调用zygote进程创建进程socket通讯
    --->创建成功后,应用进程启动
    --->应用启动成功后,调用AMS的启动Activity方法
    --->最后通知应用进程回调Activity的创建和生命周期方法


### 普通Activity启动过程

startActivity();
    startActivityForResult(intent, -1);
        startActivityForResult(intent, requestCode, null);
            mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
                ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target, requestCode, 0, null, options);
                        ActivityManagerService.startActivity
                        //这里进入AMS
                            startActivityAsUser(caller..);
                                mActivityStarter.startActivityMayWait(caller,..)
                                    //在ActivityStackSupervisor中记录startActivity开始时间
                                    mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
                                    // Save a copy in case ephemeral needs it
                                    //记录一个临时变量,防止intent改变后需要使用原intent的情况。
                                    final Intent ephemeralIntent = new Intent(intent);
                                    // Don't modify the client's object!
                                    //新建一个intent防止改变原传入的intent
                                    intent = new Intent(intent);
                                    //将intent解析成ResolveInfo
                                    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
                                    // Collect information about the target of the Intent.
                                    //将intent和rInfo中的数据解析出ActivityInfo
                                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
                                    //将mSupervisor中的非Launcher任务栈取出来
                                    stack = mSupervisor.mFocusedStack;
                                    startActivityLocked(caller,...);
                                        startActivity(caller, intent, ...);
                                            //去缓存里面获取ProcessRecord
                                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
                                            //获取intent的flag标签
                                            final int launchFlags = intent.getFlags();
                                            //获取ActivityStack
                                            final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
                                            //检查启动Activity权限
                                            boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent..)
                                            //创建ActivityRecord
                                            ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,..)
                                            startActivity(r, sourceRecord,...);
                                                result = startActivityUnchecked(r, sourceRecord,...);
                                                    
                                                    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                                                    && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
                                                        newTask = true;
                                                        //在这里面会调用创建新的taskRecord;    
                                                        result = setTaskFromReuseOrCreateNewTask();                                                    
                                                    } 
                                                    mTargetStack.startActivityLocked(mStartActivity...)
                                                    mSupervisor.resumeFocusedStackTopActivityLocked();
                                                         result = resumeTopActivityInnerLocked(prev, options);
                                                            //暂停栈顶上的Activity,将要启动的Activity进行resume确保在栈顶上
                                                            boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
                                                            mStackSupervisor.scheduleResumeTopActivities();
                                                            //调用启动activity的resume操作
                                                            next.app.thread.scheduleResumeActivity(...);
                                                            //(参考系统启动--->应用根Activity的启动过程)
                                                            mStackSupervisor.startSpecificActivityLocked(next, true, true);
                                                                //如果进程已经创建,则直接调用realStartActivityLocked
                                                                realStartActivityLocked(r, app, andResume, checkConfig);
                                                                    if(app != null && app.thread != null) {
                                                                        //开始真正进入start
                                                                        realStartActivityLocked(r, app, andResume, checkConfig);
                                                                            //调用ApplicationThread启动Activity:根据进程创建的时候调用mgr.attachApplication(mAppThread)提供的mAppThread进程binder回调
                                                                            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,...)                                                        
                                                                    }
                                                                //如果进程没有启动则会调用startProcessLocked去创建应用进程,前面有对这块的分析
                                                                mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
ActivityThread.java
     class ApplicationThread extends IApplicationThread.Stub{
        void scheduleLaunchActivity(Intent intent,...){
            ActivityClientRecord r = new ActivityClientRecord();
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
     }'
     case LAUNCH_ACTIVITY: {                
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Activity a = performLaunchActivity(r, customIntent);
                    ContextImpl appContext = createBaseContextForActivity(r);
                        ContextImpl appContext = ContextImpl.createActivityContext()
                            ContextImpl context = new ContextImpl(null, mainThread, packageInfo...)创建context
                                context.setResources(resourcesManager.createBaseActivityResources(activityToken,
                                    packageInfo.getResDir(),
                                    splitDirs,
                                    packageInfo.getOverlayDirs(),
                                    packageInfo.getApplicationInfo().sharedLibraryFiles,
                                    displayId,
                                    overrideConfiguration,
                                    compatInfo,
                                    classLoader));设置resource所以在其他地方可以使用Activity获取resource信息
                    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);通过反射获取activity对象实例                
                    Application app = r.packageInfo.makeApplication(false, mInstrumentation);创建application
                        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);创建application的context
                        app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
                            newApplication(cl.loadClass(className), context);
                                Application app = (Application)clazz.newInstance();通过反射获取application实例
                                app.attach(context);调用app的attach方法
                                    attachBaseContext(context);设置application的context
                                    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;设置apk信息
                        appContext.setOuterContext(app);设置application的context
                        instrumentation.callApplicationOnCreate(app);调用app的onCreate方法
                    appContext.setOuterContext(activity);设置Activity的context
                    activity.attach(appContext, this...)调用Activity的attach方法
                        attachBaseContext(context);设置context
                        mWindow = new PhoneWindow(this, window, activityConfigCallback);设置phoneWindow
                        mWindow.setWindowManager( );因此可以在Activity中获取window取出windowManager
                    mInstrumentation.callActivityOnCreate(activity, r.state);    
                        activity.performCreate(icicle);
                            onCreate(icicle);调用Activity的onCreate方法
                    mActivities.put(r.token, r);将Activity放入列表中
                
        
                
                    
            handleResumeActivity(r.token, false, r.isForward,
                r = performResumeActivity(token, clearHide, reason);
                    r.activity.performResume();
                        performRestart();
                        mInstrumentation.callActivityOnResume(this);
                            activity.onResume();此次调用Activity的onResume方法
到这里整个Activity的Start流程就完成了。

总结:

普通Activity启动过程省略了创建应用进程的过程,所以启动快,而创建根Activity则需要创建应用进程所以会有很多初始化工作,启动速度慢


相关文章
|
7月前
|
Java 开发者 容器
【面试题精讲】JVM-打破双亲委派机制-OSGI模块化
【面试题精讲】JVM-打破双亲委派机制-OSGI模块化
|
7月前
|
存储 缓存 Java
【面试题精讲】Java包装类缓存机制
【面试题精讲】Java包装类缓存机制
|
5天前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
5天前
|
Android开发 移动开发 小程序
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
|
4天前
|
存储 API Android开发
Android 11 中的存储机制更新,面试心得体会
Android 11 中的存储机制更新,面试心得体会
|
4天前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
|
6天前
|
消息中间件 安全 前端开发
字节面试:说说Java中的锁机制?
Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。 锁的作用主要体现在以下几个方面: 1. **互斥访问**:确保在任何时刻,只有一个线程能够访问特定的资源或执行特定的代码段。这防止了多个线程同时修改同一资源导致的数据不一致问题。 2. **内存可见性**:通过锁的获取和释放,可以确保在锁保护的代码块中对共享变量的修改对其他线程可见。这是因为 Java 内存模型(JMM)规定,对锁的释放会把修改过的共享变量从线程的工作内存刷新到主内存中,而获取锁时会从主内存中读取最新的共享变量值。 3. **保证原子性**:锁
20 1
|
6天前
|
安全 前端开发 Java
大厂面试题详解:聊一下双亲委派机制
字节跳动大厂面试题详解:聊一下双亲委派机制
29 0
|
6天前
|
运维 监控 Java
微服务心跳监测机制讲解与实现,与面试过程中如何回答这个问题
微服务心跳监测机制讲解与实现,与面试过程中如何回答这个问题
34 0
|
6天前
|
安全 编译器 C++
【Qt 面试题】Qt信号槽机制与优势与不足
【Qt 面试题】Qt信号槽机制与优势与不足
39 1