Android高级进阶(腾讯,绿网天下,哔哩哔哩,虎扑工程师联合出品)Android开发经验谈Android开发

应用程序进程启动过程

2019-03-24  本文已影响26人  慕涵盛华

一.背景

首先注意的是:这里要说的是应用程序进程的启动过程,而不是应用程序的启动过程。启动一个应用程序首先要确保该应用程序的进程已经被启动。

AMS在启动应用程序的时候会先检查对应的应用程序进程是否存在,如果不存在,就请求Zygote进程启动需要的应用程序进程。(在分析Android系统启动过程中,我们知道在ZygoteInitmain方法中会调用zygoteServer.runSelectLoop方法来等待AMS的请求)

Zygote进程通过fork自身来创建子进程,这样应用程序进程就会获得Zygote进程在启动时创建的虚拟机实例。应用程序进程在启动过程中除了获取虚拟机实例,还创建了Binder线程池消息循环,这样就可以进行进程间的通信了。

应用程序进程的启动过程可以分为两个部分,一个是AMS发送启动应用程序进程的请求,另一个是Zygote接受请求并创建应用程序进程

下面分别看一下这两个步骤的具体实现。

二.AMS发送启动应用程序进程请求

AMS会通过startProcessLocked方法Zygote进程发送请求,下面看一下该方法的实现:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ......
    try {
        try {
            final int userId = UserHandle.getUserId(app.uid);
            AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }
        //获取要创建应用程序进程的用户id
        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
        if (!app.isolated) {
            ......
            //创建组id和赋值
            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));
        }
        ......
        //ActivityThread
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkTime(startTime, "startProcess: asking zygote to start proc");
        ProcessStartResult startResult;
        if (hostingType.equals("webview_service")) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, entryPointArgs);
        } else {
            //启动应用程序进程
            startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, invokeWith, entryPointArgs);
        }
        ......
    } catch (RuntimeException e) {
        ......
    }
}

在该方法中会调用Process.start方法来启动应用程序进程,注意该方法传递的第一个参数值为:android.app.ActivityThread,后面会用到。start方法只是调用了ZygoteProcessstart方法,该类是用于保持与Zygote进程的通信状态。在它的start方法中实际调用了startViaZygote方法,下面看一下该方法的实现:

/frameworks/base/core/java/android/os/ZygoteProcess.java

private Process.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 invokeWith,String[] extraArgs)throws ZygoteStartFailedEx {
    //创建字符串列表,并将应用进程的启动参数保存在该列表中
    ArrayList<String> argsForZygote = new ArrayList<String>();
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
        argsForZygote.add("--enable-jni-logging");
    }
    ......
    synchronized(mLock) {
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}   

该方法的主要作用就是将应用进程启动的参数保存在列表argsForZygote中,然后调用了zygoteSendArgsAndGetResult方法,注意该方法传递的第一个参数是调用openZygoteSocketIfNeeded方法返回的,下面先看一下zygoteSendArgsAndGetResult方法的实现:

private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)
        throws ZygoteStartFailedEx {
    try {
        ......
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;
        writer.write(Integer.toString(args.size()));
        writer.newLine();

        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            writer.write(arg);
            writer.newLine();
        }
        writer.flush();
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = inputStream.readInt();
        result.usingWrapper = inputStream.readBoolean();
        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

从该方法的具体实现可以看出主要作用就是将应用进程的启动参数写入ZygoteState中,它是ZygoteProcess的静态内部类,用于表示与Zygote进程通信的状态。ZygoteState是传参进来的,是由openZygoteSocketIfNeeded方法返回的,下面就看一个该方法的具体实现:

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            //与Zygot进程建立连接  mSocket是一个字符串(private final String mSocket;)
            primaryZygoteState = ZygoteState.connect(mSocket);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }
    if (primaryZygoteState.matches(abi)) {
        return primaryZygoteState;
    }
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
            secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }
    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }
    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

分析Android系统启动过程分析中知道,在Zygotemain方法中会创建名字为zygote的Server端Socket。该方法中mSocket的值就是zygote,也就是说通过调用ZygoteState.connect(mSocket)方法Zygote进程建立了Socket连接,并返回ZygoteState类型的对象。上面说到zygoteSendArgsAndGetResult方法会将启动应用进程的参数写入到ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求。

三.Zygote接收请求并创建应用程序进程

上面提到在Zygote进程中会调用ZygoteServerrunSelectLoop方法来等待AMS的 请求,下面就看一下该方法的具体实现:
/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        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 {
                boolean done = peers.get(i).runOnce(this);
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

从上述代码中看出实际上是调用ZygoteConnectionrunOnce方法来处理请求数据的,下面就看一下该方法:
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;
    try {
        //获取应用程序进程的启动参数
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();
        return true;
    }
    ......
    try {
        parsedArgs = new Arguments(args);
        ......
        //创建应用程序进程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (ErrnoException ex) {
       ......
    }
    try {
        if (pid == 0) {
            // in child
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            //处理应用程序进程
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {
            // in parent...pid of < 0 means failure
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

在该方法中首先获取启动应用程序进程的参数后封装成Arguments类型的对象,然后调用Zygote.forkAndSpecialize方法,并把该对象传入来创建应用程序进程。如果pid = 0说明创建成功,则当前的代码运行在新创建的进程中,就会调用handleChildProc方法来处理应用程序进程,在该方法中实际调用了ZygoteInitzygoteInit方法,下面就看一下该方法的实现:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();
    RuntimeInit.commonInit();
    //创建Binder线程池
    ZygoteInit.nativeZygoteInit();
    //最终会调用ActivityThread的main方法(应用程序进程的入口方法)
    RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

该方法运行在应用程序进程中,主要做了两件事情:1.创建Binder线程池(nativeZygoteInit());2.执行ActivityThreadmain方法(RuntimeInit.applicationInit)。RuntimeInit.applicationInit方法中会调用
invokeStaticMain(args.startClass, args.startArgs, classLoader);,第一个传入的参数就是上面提到的android.app.ActivityThread

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws Zygote.MethodAndArgsCaller {
    Class<?> cl;

    try {
        //通过反射获取ActivityThread类
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
    Method m;
    try {
        //获取ActivityThread的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);
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }
    //抛出异常,注意传入的参数
    throw new Zygote.MethodAndArgsCaller(m, argv);
}

该方法最后会抛出异常,该异常的捕获是在ZygoteInitmain方法中:

public static void main(String argv[]) {
    ......
    } catch (Zygote.MethodAndArgsCaller caller) {
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        zygoteServer.closeServerSocket();
        throw ex;
    }
}

可以看到捕获异常后会调用MethodAndArgsCallerrun方法,该类是Zygote的静态内部类,看一下该方法的实现:

public void run() {
    try {
        //反射调用方法
        mMethod.invoke(null, new Object[] { mArgs });
    } catch (IllegalAccessException ex) {
        throw new RuntimeException(ex);
    } catch (InvocationTargetException ex) {
        Throwable cause = ex.getCause();
        if (cause instanceof RuntimeException) {
            throw (RuntimeException) cause;
        } else if (cause instanceof Error) {
            throw (Error) cause;
        }
        throw new RuntimeException(ex);
    }
}

mMethod指的就是上面传进来的ActivityThreadmain方法,这样应用程序进程就进入了ActivityThread.main方法中。下面看一下main方法都做了那些事情:
/frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    ......
    //创建主线程Looper
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    //创建Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    //开启消息轮询
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

实战

上一篇 下一篇

猜你喜欢

热点阅读