源码分析 — ActivityThread(一)之main()的调用 (Android应用进程的孵化)

本文涉及的内容,可也以被称为:《Android应用进程的孵化》

一、概述

《源码分析 — SystemServer》一文中介绍了SystemServer.main() 方法被触发的时机;
ActivityThread 中也有一个 main() 方法,那它是在什么时候被触发的呢?

源码版本:Android 23

涉及到的知识点:

  1. 源码分析 — LauncherActivity(Launcher界面)
  2. 源码分析 — Activity的启动流程

二、时序图

这里写图片描述

从这张时序图来看,整个流程分为两个部分:

  1. 系统的启动,及Socket轮询接收器的启动;
  2. 用户点击Launcher界面的应用图标来启动一个应用进程进程;

下面分着两部分进行源码分析;

三、Socket轮询器启动的源码分析

这部分涉及到以下几个类:

  1. ZygoteInit
  2. ZygoteConnection
  3. RuntimeInit
  4. MethodArgsCaller
  5. ActivityThread

3.1 类 ZygoteInit

public static void main(String argv[]) {
    try {
        // ...代码省略...

        // 本文重点:接收命令socket连接;
        runSelectLoop(abiList);
    } catch (MethodAndArgsCaller caller) {
        caller.run();//在启动子进程的过程中(最终还是调用到这里,执行ActivityThread.main()方法)
    }
}


/**
 * 从下面的注释就可以看出:
 * 在process中运行一个loop,用于接收从新连接返回的指令(commands);
 * Runs the zygote process's select loop. Accepts new connections as
 * they happen, and reads commands from connections one spawn-request's
 * worth at a time.
 * 
 * 最后抛出MethodAndArgsCaller异常,在此异常捕获的地方执行子process的main()方法;
 * @throws MethodAndArgsCaller in a child process when a main() should
 * be executed.
 */
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    // ...代码省略...

    // 无限轮训
    while (true) {
        // ...代码省略...

        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 最终执行这里ZygoteConnection.runOnce()方法;
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

3.2 类 ZygoteConnection

/**
 * 该方法主要做了3件事:
 * 1.读取子进程创建时,传递的参数信息;
 * 2.根据这些参数,从Zygote中fork一个子进程;
 * 3.对这个子进程进行处理;
 */
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    // 1.readArgumentList() 读取SystemServer发送过来的参数
    String[] args = readArgumentList();
    if (args == null) {
        return true;
    }
    // ...代码省略...

    Arguments parsedArgs = null;
    int pid = -1;
    try {
        parsedArgs = new Arguments(args);
        // ...代码省略...

        // 2.根据参数,fork一个子进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (Exception ex) {
        // ...
    }

    if (pid == 0) {
        // 3.处理子进程
        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
        return true;
    }
    // ...
}

/**
 * 从指令套接字中读取参数集,然后存储在一个String数组中,并返回该数组;
 * 
 * 该方法接收来自Process.zygoteSendArgsAndGetPid()的数据,
 * 数据的传输是通过Socket进行的;
 */
private String[] readArgumentList()
        throws IOException {
    /* 
     * 为什么这里s是一个Integer类型呢?
     * 请查看:Process.zygoteSendArgsAndGetResult()
     * s:代表参数的个数;
     */
    String s = mSocketReader.readLine();
    int argc = Integer.parseInt(s);
    // ...
    String[] result = new String[argc];
    for (int i = 0; i < argc; i++) {
        result[i] = mSocketReader.readLine();
        if (result[i] == null) {
            throw new IOException("truncated request");
        }
    }
    return result;
}

/**
 * 该方法实际就是调用了Activity.main();
 */
private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {
    // ...代码省略...

    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith, ...);
    } else {
        // 实际执行这里,其实到了这里已经很清晰了,执行过程跟SystemServer的启动一样;
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

3.3 类 RuntimeInit

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {

    applicationInit(targetSdkVersion, argv, classLoader);
}

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    // ...省略大段代码...

    // 启动指定类的main方法(startClass 代表要启动的类的类名)
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

/*
 * 这个方法的主要作用:
 * 将从Socket中获取的参数信息args,通过反射获取到即将要被调用的类的main()方法;
 */
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;

    try {
        // 1.根据类名获取class对象
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }

    Method m;
    try {
        // 2.声明main方法
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
                "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
                "Problem getting static main on " + className, ex);
    }
    // 3.校验main方法的修饰符是否是public static的;
    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }

    /* 
     * 上面全部满足后,抛出了异常,这个异常在ZygoteInit.main()中被捕获,
     * 就是上面提示要注意的地方,在异常捕获的地方执行caller.run()方法;
     */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

3.4 类 MethodAndArgsCaller

public static class MethodAndArgsCaller extends Exception
            implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            // mMethod就是SystemServer.main()方法;
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

小结: Zygote响应请求的流程

  1. Zygote 进程调用 ZygoteInit.runSelectLoop() 开启一个轮训器;
  2. SystemServer 进程发送消息到 Zygote ,在 ZygoteConnection.readArgumentList() 中接收消息;
  3. Zygote 通过 fork 创建子进程;
  4. 子进程调用android.app.ActivityThread.main() 方法;

其实,这个原理跟 HandlerLooper 原理很像,Looper开启一个轮训器,不断的从 MessageQueue 中获取最新的 Message,进而处理这个消息;
而在 ZygoteInit.runSelectLoop() 也是启动一个轮训器,从指定的 Socket 中读取数据,然后进行处理;

四、创建子过程(应用进程)的源码分析

这部分涉及到以下几个类:

  1. LauncherActivity
  2. ActivityManagerService
  3. Process

4.1 类 LauncherActivity

// 在 LauncherActivity 中,如下代码启动了一个应用程序;
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    Intent intent = adapter.intentForPosition(position);
    startActivity(intent);
}

小结:

  1. startActivity(intent) 启动一个 Activity ,经过多次的跳转后,最终将执行 ActivityManagerService.startActivity() 方法;
  2. ActivityManagerService.startActivity() 方法又经过多次跳转后,执行了 ActivityManagerService.startProcessLocked() 方法; ( 请参考《源码分析 — Activity的启动流程》)

4.2 类 ActivityManagerService

由 4.1 的小结可知,最终调用 ActivityManagerService.startProcessLocked() 方法

// 注意,这里的 entryPoint = null
private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    // ......
    try {
        // ......

        // 注意:这里设置了ActivityThread 的类名信息;
        if (entryPoint == null) 
            entryPoint = "android.app.ActivityThread";

        // 这里调用了Process.start()启动一个进程;
        Process.ProcessStartResult startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                app.info.dataDir, entryPointArgs);
        // ......
    } catch (RuntimeException e) {
        // ......
    }
}

4.3 类 Process

// processClass其实就是"android.app.ActivityThread"
public static final ProcessStartResult start(final String processClass,
         final String niceName, int uid, int gid, int[] gids,
         int debugFlags, int mountExternal, int targetSdkVersion,
         String seInfo, String abi, String instructionSet,
         String appDataDir, String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        // ......
    }
}

private static ProcessStartResult startViaZygote(final String processClass,
         final String niceName, final int uid, final int gid,
         final int[] gids, int debugFlags, int mountExternal,
         int targetSdkVersion, String seInfo, String abi,
         String instructionSet, String appDataDir,
         String[] extraArgs) throws ZygoteStartFailedEx {

    synchronized(Process.class) {
        ArrayList<String> argsForZygote = new ArrayList<String>();

        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);

        // 给argsForZygote添加参数信息;

        // 将processClass="android.app.ActivityThread"当做启动的参数传入argsForZygote中;
        argsForZygote.add(processClass);

        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }
        /* 
         * 从Zygote进程将参数信息argsForZygote通过Socket发送出去;
         * openZygoteSocketIfNeeded():打开一个Zygote的Socket通道;
         */
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

/*
 * 该方法做了以下几件事:
 * 1.开启一个Zygote的Socket通信通道;
 * 2.将启动子进程的参数写入到Socket中;
 * 3.等待ZygoteInit.readArgumentList()从Socket通道中读取参数信息,并读取子进程的pid;
 * 4.判断子进程的pid<0是否成立,从而判断子进程是否fork成功;
 */
private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
   try {
        /**
         * 从下面这段注释可以看出,zygoteState.writer在写入时,
         * ZygoteInit.readArgumentList()就能读取到相应的参数信息;
         * 
         * See com.android.internal.os.ZygoteInit.readArgumentList()
         * Presently the wire format to the zygote process is:
         * a) a count of arguments (argc, in essence)
         * b) a number of newline-separated argument strings equal to count
         * 
         * 在Zygote进程获取到这些参数后,就会返回一个子进程的pid(进程Id);如果失败了,pid=-1;
         * After the zygote process reads these it will write the pid of
         * the child or -1 on failure, followed by boolean to
         * indicate whether a wrapper process was used.
         */
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;

        /*
         * 这里第一行输入的是参数的个数,所以这就是为什么在ZygoteInit.readArgumentList()方法中
         * 获取到第一行数据s后,将它转换成Integer类型的原因;
         */
        writer.write(Integer.toString(args.size()));
        writer.newLine();

        // 将参数 args 一行行写入Socket中;
        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            if (arg.indexOf('\n') >= 0) {
                throw new ZygoteStartFailedEx(
                        "embedded newlines not allowed");
            }
            writer.write(arg);
            writer.newLine();
        }
        writer.flush();

        // Should there be a timeout on this?
        ProcessStartResult result = new ProcessStartResult();
        // 获取到新的子进程的Pid
        result.pid = inputStream.readInt();
        if (result.pid < 0) {// 如果pid < 0,就说明子进程fork失败;
            throw new ZygoteStartFailedEx("fork() failed");
        }
        result.usingWrapper = inputStream.readBoolean();
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

小结:Process

  1. Process.start() 中接收了需要启动的类 android.app.ActivityThread
  2. Process.startViaZygote() 方法中,添加启动子进程所需的参数信息;
  3. 执行 Process.zygoteSendArgsAndGetResult() 方法;
    1. 开启一个Zygote的Socket通信通道;
    2. 将启动子进程的参数写入到Socket中;
    3. 等待ZygoteInit.readArgumentList()从Socket通道中读取参数信息,并读取子进程的pid;
    4. 判断子进程的pid<0是否成立,从而判断子进程是否fork成功;
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值