0%

Android源码之进程启动过程

概要

  • API21
  • AMS 启动进程
  • Zygote fork进程
  • 应用端初始化

上一张调用流程的时序图:

在启动四大组件时,会检查组件所在的进程是否运行,否则启动该组件指定的进程。
先上一张流程图,以startActivity举例。
在之前 Android源码之Activity启动过程 中提到,AMS启动Activity时,会执行到startSpecificActivityLocked方法,调用startProcessLocked启动进程

AMS启动进程处理

  • 1 AMS.startProcessLocked

    1
    2
    3
    4
    //info = ApplicationInfo
    app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
    entryPoint = "android.app.ActivityThread";
    Process.start(entryPoint,app.processName, uid, uid, gids, ...);

    可以看到这个函数主要是准备相关的数据。

    • 创建一个进程相关的数据记录。
    • entryPoint值为 android.app.ActivityThread ,表明新进程的入口类。
      这个参数会一路传下去,在Zygote fork进程后,子进程会加载ActivityThread类的main方法。
    • 调用Process.start创建进程
  • 2 Process.start

    start方法直接调用startViaZygote,看实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ProcessStartResult start(...){
    startViaZygote(...)
    }

    private static ProcessStartResult startViaZygote(final String processClass,final String niceName,..){
    ArrayList<String> argsForZygote = new ArrayList<String>();
    argsForZygote.add("--runtime-init");
    argsForZygote.add(processClass);
    //...
    zygoteSendArgsAndGetResult(...,argsForZygote)
    }

    startViaZygote方法很简单,将传入的以及默认的参数重新拼装,以 List<String> 形式往下调用

  • 3 Process.zygoteSendArgsAndGetResult

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args){
    final BufferedWriter writer = zygoteState.writer;
    final DataInputStream inputStream = zygoteState.inputStream;
    int sz = args.size();
    for (int i = 0; i < sz; i++) {
    String arg = args.get(i);
    writer.write(arg);
    writer.newLine();
    }
    writer.flush();
    ProcessStartResult result = new ProcessStartResult();
    result.pid = inputStream.readInt();
    return result;
    }

    有两个重要的变量

    • zygoteState.writer
    • zygoteState.inputStream

    由名知意,这是一个输入/输入流。ZygoteInit在main函数中注册了一个SocketServer,之后不断监听输入、输出,进行处理。
    函数逻辑很简单:通过Socket方式将之前准备的参数指令传送给ZygoteInit,由ZygoteInit进行处理。

Zygote 处理

  • 8 先看ZygoteInit的mian函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static void main(String argv[]) {
    try {
    //1. 打开Socket
    registerZygoteSocket(socketName);
    preload();
    //2. 监听输入输出
    runSelectLoop(abiList);
    //3. 关闭
    closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
    //4. 执行反射ActivityThread方法
    caller.run();
    } catch (RuntimeException ex) {
    //...
    }
    }

    我们不去纠结1、3步的具体实现,只要知道在函数中开启了一个Socket服务,并在适合的时机关闭。
    重点关注2、4两步
    在第二步中,进行了子进程的fork操作,并将进程信息以异常的形式抛上来。
    第四步,捕获到进程信息后,执行run方法

  • 4 先看第二步runSelectLoop实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    private static void runSelectLoop(String abiList){
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    FileDescriptor[] fdArray = new FileDescriptor[4];
    fds.add(sServerSocket.getFileDescriptor());
    while (true) {
    index = selectReadable(fdArray);
    if (index < 0) {
    throw new RuntimeException("Error in select()");
    } else if (index == 0) {
    //接收到一个Socket连接
    ZygoteConnection newPeer = acceptCommandPeer(abiList);
    peers.add(newPeer);
    fds.add(newPeer.getFileDescriptor());
    } else {
    //处理连接
    done = peers.get(index).runOnce();
    //后续清理...
    }
    }
    }

    函数中开启了一个死循环,不断获取socket上的连接。
    当接收到一个连接 ZygoteConnection 后,先存到一个List中
    在下次循环时,调用ZygoteConnection的runOnce方法

  • 5 runOnce

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /** ZygoteConnection **/
    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    args = readArgumentList();
    parsedArgs = new Arguments(args);
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, ...parsedArgs.niceName, ..);
    if (pid == 0) {
    handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
    }else{
    handleParentProc
    }
    }

    在第2行代码中,解析之前一路传下来的参数,而参数中包含了入口类等各种信息。
    第四行代码,由函数名可知,__进行了进程的fork操作__。
    第5行和第7行判断当前属于哪个进程。
    当pid=0时,进入子进程的处理流程handleChildProc

  • 6 handleChildProc

    1
    2
    3
    4
    5
    /** ZygoteInit **/
    private void handleChildProc(Arguments parsedArgs,...)throws ZygoteInit.MethodAndArgsCaller){
    cloader = new PathClassLoader(parsedArgs.classpath,ClassLoader.getSystemClassLoader());
    ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
    }

    创建了一个ClassLoader,ClassLoader指向待启动应用的代码
    执行ZygoteInit.invokeStaticMain方法。

  • 7 invokeStaticMain

    1
    2
    3
    4
    5
    6
    /** ZygoteInit **/
    static void invokeStaticMain(ClassLoader loader,String className, String[] argv)throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl = loader.loadClass(className);
    Method m = cl.getMethod("main", new Class[] { String[].class });
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

    参数className是之前一路传下来的 android.app.ActivityThread
    函数通过应用的ClassLoader,反射到代码中ActivityThread的main函数对象
    最后,创建一个MethodAndArgsCaller对象,以异常形式抛出。
    在时序图的第8步中,ZygoteInit的main方法中catch了这个异常,执行了run方法

  • 9 run

    ZygoteInit.MethodAndArgsCaller

    1
    2
    3
    public void run() {
    mMethod.invoke(null, new Object[] { mArgs });
    }

    方法很简单,反射执行方法。
    我们知道这个mMethod实际上指向的是应用ActivityThread的main方法。
    进入应用端,看ActivityThread的main方法实现。

应用端处理

  • 10 main

    1
    2
    3
    4
    5
    6
    7
    /** ActivityThread **/
    public static void main(String[] args) {
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    Looper.loop();
    }

    main方法包括三部分

    • Looper.prepareMainLooper
    • thread.attach
    • Looper.loop
  • 11 prepareMainLooper

    1
    2
    3
    4
    /** Looper **/
    public static void prepare() {
    sThreadLocal.set(new Looper());
    }

    创建一个Loper对象,并保存到当前线程的ThreadLocal中

  • 12 attach

    1
    2
    3
    4
    5
    6
    /** ActivityThread **/
    ActivityManager mgr = ActivityManagerNative.getDefault();
    mgr.attachApplication(mAppThread);
    mInstrumentation = new Instrumentation();
    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
    mInitialApplication.onCreate();

    第三行代码,通过binder调用,将进程的Binder关联到ASM中
    创建Application对象,并调用我们熟悉的的onCreate方法
    探究Application对象的创建过程

  • 13 attachApplication

  • 14 attachApplicationLocked

    1
    2
    3
    4
    5
    /** AMS **/
    private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
    List<ProviderInfo> providers = generateApplicationProvidersLocked(app) ;
    thread.bindApplication(processName, appInfo, ...)
    }

    在AMS中,做了很多事,其中收集了App的Provider信息,再次通过binder调用到App端的进程中

  • 15 bindApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /** ActivityThread **/
    public final void bindApplication(String processName, ApplicationInfo appInfo ...){
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    //...
    sendMessage(H.BIND_APPLICATION, data);
    }

    组装AMS端传过来的数据,发送到Handler上,我们知道,这个Handler是Actvith上的mH对象,在handleMessage方法中又分发到了ActivityThread上的handleBindApplication中

  • 16,17 handleBindApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    private void handleBindApplication(AppBindData data) {
    mInstrumentation = new Instrumentation();
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    List<ProviderInfo> providers = data.providers;
    if (providers != null) {
    installContentProviders(app, providers);
    }
    mInstrumentation.callApplicationOnCreate(app);
    }

    在方法中干了三件事

    • 创建Application对象(18)
    • 初始化Provider (本篇文章不关心)
    • 调用mInstrumentation.callApplicationOnCreate (21)
  • 18 makeApplication

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /** LoadedApk **/
    public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {
    if (mApplication != null) {
    return mApplication;
    }
    String appClass = mApplicationInfo.className;
    java.lang.ClassLoader cl = getClassLoader();
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);
    }

    成员变量appClass为Application的全限定名,默认为android.app.Application。
    或者是在manifest中注册的自定义Application全限定名。
    在第8行中,为Application创建打了一个ContextImpl
    调用Instrumention的newApplication方法初始化Application

  • 19 createAppContext

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public Application newApplication(ClassLoader cl, String className, Context context){
    //函数调用
    return newApplication(cl.loadClass(className), context);
    }
    static public Application newApplication(Class<?> clazz, Context context){
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
    }

    可以看到,newApplication函数中,创建了Application对象,并调用了attach方法。

    由此可知,在App层面,attach方法进程启动过程中所能接触到的最早的时机。

  • 20 略

  • 21 callApplicationOnCreate

    1
    2
    3
    public void callApplicationOnCreate(Application app) {
    app.onCreate();
    }

    很简单,调用了我们经常接触到的Application的onCreate方法

  • 22 略

  • 23 loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /** Looper **/
    public static void loop() {
    Looper me = myLooper();
    MessageQueue queue = me.mQueue;
    while (true) {
    Message msg = queue.next(); // might block
    if (msg != null) {
    msg.target.dispatchMessage(msg);
    }
    msg.recycle();
    }
    }

    可以看到,最后在UI线程中开启一个死循环,不断轮询消息,并做分发处理。

至此,应用进程启动过程分析完毕