文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android应用程序的启动流程是什么

2023-07-05 19:08

关注

本篇内容介绍了“Android应用程序的启动流程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

应用进程的启动流程

本文基于Android 11,主要分析应用程序的启动流程,会直接定位到ActivityStackSupervisor.startSpecificActivity函数开始,因为该函数前面的内容主要在Activity的启动流程中,可以通过这部分的文章来阅读。

看源码流程,需要戒骄戒躁,心态好。配合源码使用,建议先收藏,夜深人静,心血来潮再看。

通过分析应用进程的启动流程,可以得到:

1、ActivityStackSupervisor.startSpecificActivity

ATMS有一个ProcessMap<WindowProcessController>类型的mProcessNames ,用于存储封装了已启动进程信息ProcessRecord和窗口信息Windows的WindowProcessController实例。WindowProcessController用于协调ActivityManger管理ProcessReocrd和WindwManger管理WIndow和Activity的关系。

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {    // Is this activity's application already running?    final WindowProcessController wpc =            mService.getProcessController(r.processName, r.info.applicationInfo.uid);    boolean knownToBeDead = false;    if (wpc != null && wpc.hasThread()) {        realStartActivityLocked(r, wpc, andResume, checkConfig);        return;        ...        knownToBeDead = true;    }    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();    final boolean isTop = andResume && r.isTopRunningActivity();    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");}

这里的mService是ActivityTaskManagerService的实例,通过getProcessController函数获得当前wpc对象,判断当前启动应用进程是否启动wpc != null && wpc.hasThread(),如果条件成立,则开始真正启动一个未启动过的Activity,通过realStartActivityLocked;条件不成立,则调用mService的startProcessAsync启动当前Activity的所在的进程。即startSpecificActivity函数是启动进程和启动Activity的一个分界点。

2、ATMS.startProcessAsync

PooledLambda.obtainMessage函数是Lambda的调用方式,表示调用ActivityManagerInternal的startProcess函数,后续则是其参数。并返回一个Message对象,发给Handler类型的mH。

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,        String hostingType) {    final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,            mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,            isTop, hostingType, activity.intent.getComponent());    mH.sendMessage(m);}

抽象类ActivityManagerInternal的继承类定义在ActivityManagerService的内部类LocalService。

public final class LocalService extends ActivityManagerInternal

3、LocalService.startProcess

@Overridepublic void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,        boolean isTop, String hostingType, ComponentName hostingName) {    startProcessLocked(processName, info, knownToBeDead, 0 ,            new HostingRecord(hostingType, hostingName, isTop),            ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false ,            false , true );  }

4、startProcessLocked函数

final ProcessRecord startProcessLocked(String processName,        ApplicationInfo info, boolean knownToBeDead, int intentFlags,        HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,        boolean isolated, boolean keepIfLarge) {    return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,            hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 ,            keepIfLarge, null , null ,            null , null );}

5、ProcessList.startProcessLocked

ProcessList类的startProcessLocked函数,有几个重载函数,第一个调用。

在 !isolated,判断了启动IntentFlag是否后台运行,是的话,直接拒绝。否则清理AMS中发生过Crash的进程(当前应用)。

分析一:创立当前应用进程的描述ProcessRecord。

判断当前系统是否启动完毕,未启动完毕,将进程信息缓存到AMS的mProcessesOnHold中。

分析二:调用了另外一个重载函数。

    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,            boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,            int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,            boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,            Runnable crashHandler) {        long startTime = SystemClock.uptimeMillis();        ProcessRecord app;//isolated传递进来是false,        if (!isolated) {//从mProcessNames缓存获取,由于是首次创建,null            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);            checkSlow(startTime, "startProcess: after getProcessRecord");//判断要启动进程是否后台运行,直接return null            if ((intentFlags &amp; Intent.FLAG_FROM_BACKGROUND) != 0) {                if (mService.mAppErrors.isBadProcessLocked(info)) {                    return null;                }            } else {                //重置进程的crash状态,使其处于正常状态                mService.mAppErrors.resetProcessCrashTimeLocked(info);                if (mService.mAppErrors.isBadProcessLocked(info)) {                    mService.mAppErrors.clearBadProcessLocked(info);                    if (app != null) {                        app.bad = false;                    }                }            }        } else {            app = null;        }        ProcessRecord precedence = null;        if (app != null &amp;&amp; app.pid &gt; 0) {            if ((!knownToBeDead &amp;&amp; !app.killed) || app.thread == null) {                app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);                return app;            }            ProcessList.killProcessGroup(app.uid, app.pid);            precedence = app;            app = null;        }        if (app == null) {// 分析一、创建新的应用进程描述ProcessRocrd//内部会将自己添加到mProcessNames中app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);if (app == null) {                return null;            }//此时三者都是null            app.crashHandler = crashHandler;            app.isolatedEntryPoint = entryPoint;            app.isolatedEntryPointArgs = entryPointArgs;            if (precedence != null) {                app.mPrecedence = precedence;                precedence.mSuccessor = app;            }        } else {            app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);        }        // If the system is not ready yet, then hold off on starting this        // process until it is.        if (!mService.mProcessesReady                &amp;&amp; !mService.isAllowedWhileBooting(info)                &amp;&amp; !allowWhileBooting) {            if (!mService.mProcessesOnHold.contains(app)) {                mService.mProcessesOnHold.add(app);            }            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,                    "System not ready, putting on hold: " + app);            checkSlow(startTime, "startProcess: returning with proc on hold");            return app;        }分析二:        final boolean success =                startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);        checkSlow(startTime, "startProcess: done starting proc!");        return success ? app : null;    }

6、ProcessList.startProcessLocked重载

再次调用另外一个重载函数。

final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,        int zygotePolicyFlags, String abiOverride) {    return startProcessLocked(app, hostingRecord, zygotePolicyFlags,            false , false ,            false , abiOverride);}

重载函数,这个重载函数处理逻辑很长,主要给前面创建的ProcessRecord类型的app设置各种属性。例如外部存储挂载模式,应用进程运行模式,abi架构等等,其中包括最重要一点就是分析一,确定要启动进程的的类名:android.app.ActivityThread。分析二,继续调用重载函数。

    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,            boolean mountExtStorageFull, String abiOverride) {...            app.gids = gids;            app.setRequiredAbi(requiredAbi);            app.instructionSet = instructionSet;            final String seInfo = app.info.seInfo                    + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);            //分析一:确定要启动应用程序的类名            final String entryPoint = "android.app.ActivityThread";//分析二:调用另外一个重载函数            return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,                    runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,                    instructionSet, invokeWith, startTime);        } catch (RuntimeException e) {  ...        }    }

重载函数:也是设置一些属性,然后调用startProcess函数。

 boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,            int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,            String seInfo, String requiredAbi, String instructionSet, String invokeWith,            long startTime) {            ...            final Process.ProcessStartResult startResult = startProcess(hostingRecord,                    entryPoint, app,                    uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,                    requiredAbi, instructionSet, invokeWith, startTime);            handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,                    startSeq, false);           ...        }    }

7、ProcessList.startProcess

ProcessList类的startProcess函数会根据hostingRecord属性mHostingZygote判断走不同的创建分支,前面创建使用默认值,所以走了else分支。通过 Process.start函数创建新的应用进程。

Process.start的一路调用:

Process.start=&gt;ZygoteProcess.start=&gt;ZygoteState.start=&gt;ZygoteState.startViaZygote

8、ZygoteState.startViaZygote

startViaZygote函数,主要是将传递进来的参数拼接成成字符串和收集起来。其中processClass是

private Process.ProcessStartResult startViaZygote(...)                                                  throws ZygoteStartFailedEx {        //根据传递进来的参数,拼接成字符串并收集到ArrayList&lt;String&gt;类型argsForZygote        //将作为新应用程序的主函数的参数        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),                                          zygotePolicyFlags,                                          argsForZygote);}

9、ZygoteState.openZygoteSocketIfNeeded

zygoteSendArgsAndGetResult的第一个参数,调用了openZygoteSocketIfNeeded函数。尝试建立与Socket的连接(如果之前未建立的话)。我们知道Zygote进程在创建的过程,会调用runSelectLoop函数,创建Server端的Socket,一直等待来自AMS的Client端的Socket创建进程请求。

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {    try {    //建立和Zygote的Socket连接        attemptConnectionToPrimaryZygote();//匹配abi的架构。在Zygote的创建对应四种模式:32,32_64和64,64_32//32,64        if (primaryZygoteState.matches(abi)) {            return primaryZygoteState;        }//主要架构模式不配,匹配第二种 32_64,64_32        if (mZygoteSecondarySocketAddress != null) {            // The primary zygote didn't match. Try the secondary.            attemptConnectionToSecondaryZygote();            if (secondaryZygoteState.matches(abi)) {                return secondaryZygoteState;            }        }    } catch (IOException ioe) {        throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);    }    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);}

attemptConnectionToPrimaryZygote函数主要通过底层的LocalSocket创建与Zygote进程的Socket连接,并获得输入流zygoteInputStream和输出流zygoteOutputWriter。

private void attemptConnectionToPrimaryZygote() throws IOException {    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {        primaryZygoteState =                ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);        maybeSetApiBlacklistExemptions(primaryZygoteState, false);        maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);    }}

和Zygote进程的Server端Socket建立连接后,就是开始往Socket写数据了。

10、attemptZygoteSendArgsAndGetResult

回到第8步调用了zygoteSendArgsAndGetResult函数,又调用了attemptZygoteSendArgsAndGetResult函数。

zygoteSendArgsAndGetResult=&gt;attemptZygoteSendArgsAndGetResult

11、attemptZygoteSendArgsAndGetResult

到这里,通过Socket的方式向Zygote进程写进前面拼接好的参数,Zygote在Server端的Socket接收到数据之后,会执行创建动作。在返回的result.pid>=0表示创建成功,并运行在新的进程。

    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(            ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {        try {            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;            zygoteWriter.write(msgStr);            zygoteWriter.flush();            Process.ProcessStartResult result = new Process.ProcessStartResult();            result.pid = zygoteInputStream.readInt();            result.usingWrapper = zygoteInputStream.readBoolean();            if (result.pid &lt; 0) {                throw new ZygoteStartFailedEx("fork() failed");            }            return result;        } catch (IOException ex) {            zygoteState.close();            Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "                    + ex.toString());            throw new ZygoteStartFailedEx(ex);        }    }

12、Zygote.main

在Zygote的启动流程过程,调用了ZygoteInit的main函数,因为Zygote是通过fork自身来创建其他进程,所以需要根据传递进来的参数,进行判断是启动什么类型的进程,例如自身isPrimaryZygote=true,或者SystemServer进程。然后通过ZygoteServer.runSelectLoop函数,等待其他进程请求创建新的进程。

    public static void main(String argv[]) {        ZygoteServer zygoteServer = null;        Runnable caller;        try {        ...            boolean startSystemServer = false;            String zygoteSocketName = "zygote";            String abiList = null;            boolean enableLazyPreload = false;            for (int i = 1; i &lt; argv.length; i++) {                if ("start-system-server".equals(argv[i])) {                    startSystemServer = true; //判断是否SystemServer进程                } else if ("--enable-lazy-preload".equals(argv[i])) {                    enableLazyPreload = true;                } else if (argv[i].startsWith(ABI_LIST_ARG)) {                    abiList = argv[i].substring(ABI_LIST_ARG.length());                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {                //SCOKET_NAME_ARG="--socket-name=",根据参数得到SocketName                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());                } else {                    throw new RuntimeException("Unknown command line argument: " + argv[i]);                }            }    //PRIMARY_SOCKET_NAME=zygote            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);         gcAndFinalize();            Zygote.initNativeState(isPrimaryZygote);            ZygoteHooks.stopZygoteNoThreadCreation();            zygoteServer = new ZygoteServer(isPrimaryZygote);            if (startSystemServer) {            //启动SystemServer进程                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);                if (r != null) {                    r.run();                    return;                }            }   //循环等待AMS来请求创建新的进程            caller = zygoteServer.runSelectLoop(abiList);        } catch (Throwable ex) {            Log.e(TAG, "System zygote died with exception", ex);            throw ex;        } finally {            if (zygoteServer != null) {                zygoteServer.closeServerSocket();            }        }//调用新的进程主函数        if (caller != null) {            caller.run();        }    }

13、ZygoteServer.runSelectLoo

这里只关注ZygoteServer.runSelectLoop函数,接受Socket客户端数据。

     Runnable runSelectLoop(String abiList) {        while (true) {         ...            ZygoteConnection connection = peers.get(pollIndex);            final Runnable command = connection.processOneCommand(this);...            if (mIsForkChild) {                return command;            }            ....          }}

14、ZygoteConnection.processOneCommand

runSelctLoop主要是从循环中检测是否有连接建立,建立之后执行ZygoteConnection的processOneCommand函数,并返回一个Runable类型的command对象。

Runnable processOneCommand(ZygoteServer zygoteServer) {    ...    args = Zygote.readArgumentList(mSocketReader);    //根据参数内容,作其他类型的处理    ...    //创建进程,调用底层nativeForkAndSpecialize方法,通过fork当前进程来创建一个子线程。    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,            parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,            parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,            parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,            parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,            parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);    ...    if (pid == 0) {        //设置mIsForkChild=true        zygoteServer.setForkChild();       //关闭Socket连接        zygoteServer.closeServerSocket();        IoUtils.closeQuietly(serverPipeFd);        serverPipeFd = null;       //执行子进程内容        return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);    }     ...}

15、handleChildProc

handleChildProc函数。

private Runnable handleChildProc(ZygoteArguments parsedArgs,        FileDescriptor pipeFd, boolean isZygote) {        ...        if (!isZygote) {            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,                    parsedArgs.mDisabledCompatChanges,                    parsedArgs.mRemainingArgs, null );        } else {            return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,                    parsedArgs.mRemainingArgs, null );        }}

16、 ZygoteInit.zygoteInit

public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,        String[] argv, ClassLoader classLoader) {    RuntimeInit.commonInit();    ZygoteInit.nativeZygoteInit();//为新进程创建Binder线程池    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,            classLoader);}

以前还以为每个进程共用一个Binder线程池,现在知道每个进程都有自己的Binder线程池进行IPC。

17、RuntimeInit.applicationInit

    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,            String[] argv, ClassLoader classLoader) {        final Arguments args = new Arguments(argv);         return findStaticMain(args.startClass, args.startArgs, classLoader);    }

这里的args.startClass就是Socket客户端传递下来的android.app.ActivityThread。

18、RuntimeInit.findStaticMain

RuntimeInit.findStaticMain函数主要通过反射创建ActivityThread类的实例,并反射主函数main,然后封装到MethodAndArgsCaller实例中返回。

protected static Runnable findStaticMain(String className, String[] argv,        ClassLoader classLoader) {    ...    Class&lt;?&gt; cl = Class.forName(className, true, classLoader);    Method m = cl.getMethod("main", new Class[] { String[].class });    ...    return new MethodAndArgsCaller(m, argv);}

MethodAndArgsCaller类继承自Runable,并在其run函数,调用主函数方法。

static class MethodAndArgsCaller implements Runnable {        private final Method mMethod;        private final String[] mArgs;    public MethodAndArgsCaller(Method method, String[] args) {        mMethod = method;        mArgs = args;    }    public void run() {        ...        mMethod.invoke(null, new Object[] { mArgs });        ...    }}

随着findStaticMain函数方法栈一路返回到runSelectLoop函数,因为mIsForkChild是true,所以MethodAndArgsCaller对象返回到ZygoteInit的main函数,并赋值给caller变量。main函数最后调用caller的run函数。即执行了ActivityThread的主函数main。

本来自己还有个疑惑,fork子进程之后,并caller的run函数,已经退出了Zygote进程的runSelectLoop循环等待。怎么继续去接收AMS新的请求。原来如此,fork子进程后,后续的代码都运行在了子进程,这里return其实是子进程了。

一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

19、进程ActivityThread.main。

public static void main(String[] args) {    Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    thread.attach(false, startSeq);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    Looper.loop();}

ActivityThread的主函数,创建了ActivityThread进程,并启动了消息循环队列,代表着当前进程的主线程已启动。

知识点

疑问点

“Android应用程序的启动流程是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯