相关文章
Android系统架构与系统源码目录
Android系统启动流程(一)解析init进程启动过程
Android系统启动流程(二)解析Zygote进程启动过程
Android系统启动流程(三)解析SyetemServer进程启动过程
Android系统启动流程(四)Launcher启动过程与系统启动流程

前言

在此前我讲过Android系统的启动流程,系统启动后,我们就比较关心应用程序是如何启动的,这一篇我们来一起学习Android7.0 应用程序进程启动过程,需要注意的是“应用程序进程启动过程”,而不是应用程序启动过程。关于应用程序启动过程,我会在后续系列的文章中讲到。希望阅读这篇文章前先阅读本文列出的相关文章,要不你一脸蒙蔽,就别怪我了。

1.应用程序进程概述

要想启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经被启动。ActivityManagerService在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程将需要的应用程序进程启动。在Android系统启动流程(二)解析Zygote进程启动过程这篇文章中,我提到了Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程的。我们知道Zygote进程通过fock自身创建的应用程序进程,这样应用程序程序进程就会获得Zygote进程在启动时创建的虚拟机实例。当然,在应用程序创建过程中除了获取虚拟机实例,还可以获得Binder线程池和消息循环,这样运行在应用进程中应用程序就可以方便的使用Binder进行进程间通信以及消息处理机制了。先给出应用程序进程启动过程的时序图,然后对每一个步骤进行详细分析,如下图所示。

2.应用程序进程创建过程

发送创建应用程序进程请求

ActivityManagerService会通过调用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();}int uid = app.uid;//1int[] gids = null;int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;if (!app.isolated) {.../*** 2 对gids进行创建和赋值*/if (ArrayUtils.isEmpty(permGids)) {gids = new int[2];} else {gids = new int[permGids.length + 2];System.arraycopy(permGids, 0, gids, 2, permGids.length);}gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));}...if (entryPoint == null) entryPoint = "android.app.ActivityThread";//3Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +app.processName);checkTime(startTime, "startProcess: asking zygote to start proc");/*** 4*/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) {...}}...}

在注释1处的达到创建应用程序进程的用户ID,在注释2处对用户组ID:gids进行创建和赋值。注释3处如果entryPoint 为null则赋值为"android.app.ActivityThread"。在注释4处调用Process的start函数,将此前得到的应用程序进程用户ID和用户组ID传进去,第一个参数entryPoint我们得知是"android.app.ActivityThread",后文会再次提到它。接下来我们来查看Process的start函数,如下所示。
frameworks/base/core/java/android/os/Process.java

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) {...}
}

start函数中只调用了startViaZygote函数:
frameworks/base/core/java/android/os/Process.java

   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) {/*** 1*/ArrayList<String> argsForZygote = new ArrayList<String>();argsForZygote.add("--runtime-args");argsForZygote.add("--setuid=" + uid);argsForZygote.add("--setgid=" + gid);...if (gids != null && gids.length > 0) {StringBuilder sb = new StringBuilder();sb.append("--setgroups=");int sz = gids.length;for (int i = 0; i < sz; i++) {if (i != 0) {sb.append(',');}sb.append(gids[i]);}argsForZygote.add(sb.toString());}...argsForZygote.add(processClass);if (extraArgs != null) {for (String arg : extraArgs) {argsForZygote.add(arg);}}return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);}}

在注释1处创建了字符串列表argsForZygote ,并将启动应用进程的启动参数保存在argsForZygote中,函数的最后会调用zygoteSendArgsAndGetResult函数,需要注意的是,zygoteSendArgsAndGetResult函数中第一个参数中调用了openZygoteSocketIfNeeded函数,而第二个参数是保存应用进程的启动参数的argsForZygote。zygoteSendArgsAndGetResult函数如下所示。
frameworks/base/core/java/android/os/Process.java

  private static 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();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();result.pid = inputStream.readInt();if (result.pid < 0) {throw new ZygoteStartFailedEx("fork() failed");}result.usingWrapper = inputStream.readBoolean();return result;} catch (IOException ex) {zygoteState.close();throw new ZygoteStartFailedEx(ex);}}

zygoteSendArgsAndGetResult函数主要做的就是将传入的应用进程的启动参数argsForZygote,写入到ZygoteState中,结合上文我们知道ZygoteState其实是由openZygoteSocketIfNeeded函数返回的,那么我们接着来看openZygoteSocketIfNeeded函数,代码如下所示。
frameworks/base/core/java/android/os/Process.java

private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {if (primaryZygoteState == null || primaryZygoteState.isClosed()) {try {primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//1} catch (IOException ioe) {throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);}}if (primaryZygoteState.matches(abi)) {//2return primaryZygoteState;}// The primary zygote didn't match. Try the secondary.if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {try {secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);//3} 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);

在讲到Zygote进程启动过程时我们得知,在Zygote的main函数中会创建name为“zygote”的Server端Socket。在注释1处会调用ZygoteState的connect函数与名称为ZYGOTE_SOCKET的Socket建立连接,这里ZYGOTE_SOCKET的值为“zygote”。注释2处如果连接name为“zygote”的Socket返回的primaryZygoteState与当前的abi不匹配,则会在注释3处连接name为“zygote_secondary”的Socket。这两个Socket区别就是:name为"zygote”的Socket是运行在64位Zygote进程中的,而name为“zygote_secondary”的Socket则运行在32位Zygote进程中。既然应用程序进程是通过Zygote进程fock产生的,当要连接Zygote中的Socket时,也需要保证位数的一致。

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

Socket进行连接成功并匹配abi后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult函数中讲过,会将应用进程的启动参数argsForZygote写入到ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main函数,如下所示。

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

public static void main(String argv[]) {...try {...       //注册Zygote用的SocketregisterZygoteSocket(socketName);//1...//预加载类和资源preload();//2...if (startSystemServer) {//启动SystemServer进程startSystemServer(abiList, socketName);//3}Log.i(TAG, "Accepting command socket connections");//等待客户端请求runSelectLoop(abiList);//4closeServerSocket();} catch (MethodAndArgsCaller caller) {caller.run();} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}

这些内容在Android系统启动流程(二)解析Zygote进程启动过程讲过,但为了更好的理解我再讲一遍。注释1处通过registerZygoteSocket函数来创建一个Server端的Socket,这个name为”zygote”的Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程。注释2处用来预加载类和资源。注释3处用来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。注释4处调用runSelectLoop函数来等待ActivityManagerService的请求。我们就来查看runSelectLoop函数:

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

 private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();//2fds.add(sServerSocket.getFileDescriptor());peers.add(null);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 {boolean done = peers.get(i).runOnce();//1if (done) {peers.remove(i);fds.remove(i);}}}}}

当有ActivityManagerService的请求数据到来时会调用注释1处的代码,结合注释2处的代码,我们得知注释1处的代码其实是调用ZygoteConnection的runOnce函数来处理请求的数据:
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

 boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {String args[];Arguments parsedArgs = null;FileDescriptor[] descriptors;try {args = readArgumentList();//1descriptors = mSocket.getAncillaryFileDescriptors();} catch (IOException ex) {Log.w(TAG, "IOException on command socket " + ex.getMessage());closeSocket();return true;}
...try {parsedArgs = new Arguments(args);//2.../*** 3 */pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);} catch (ErrnoException ex) {....}try {if (pid == 0) {// in childIoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);return true;} else {// in parent...pid of < 0 means failureIoUtils.closeQuietly(childPipeFd);childPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);}}

在注释1处调用readArgumentList函数来获取应用程序进程的启动参数,并在注释2处将readArgumentList函数返回的字符串封装到Arguments对象parsedArgs中。注释3处调用Zygote的forkAndSpecialize函数来创建应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。forkAndSpecialize函数主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明是在新创建的子进程中执行的,就会调用handleChildProc函数来启动这个子进程也就是应用程序进程,如下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

 private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {...RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null /* classLoader */);}}

handleChildProc函数中调用了RuntimeInit的zygoteInit函数,如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");redirectLogStreams();commonInit();nativeZygoteInit();//1applicationInit(targetSdkVersion, argv, classLoader);//2}

注释1处会在新创建的应用程序进程中创建Binder线程池,这个在下一篇文章会详细介绍。在注释2处调用了applicationInit函数:
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {...final Arguments args;try {args = new Arguments(argv);} catch (IllegalArgumentException ex) {Slog.e(TAG, ex.getMessage());       return;}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);invokeStaticMain(args.startClass, args.startArgs, classLoader);//1}

在applicationInit中会在注释1处调用invokeStaticMain函数,需要注意的是第一个参数args.startClass,这里指的就是此篇文章开头提到的参数:android.app.ActivityThread。接下来我们查看invokeStaticMain函数,如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {Class<?> cl;try {cl = Class.forName(className, true, classLoader);//1} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className,ex);}Method m;try {m = cl.getMethod("main", new Class[] { String[].class });//2} catch (NoSuchMethodException ex) {throw new RuntimeException("Missing static main on " + className, ex);}...throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
}

可以看到注释1处通过反射来获得android.app.ActivityThread类,接下来在注释2处来获得ActivityThread的main函数,并将main函数传入到注释3处的ZygoteInit中的MethodAndArgsCaller类的构造函数中,MethodAndArgsCaller类内部会通过反射调用ActivityThread的main函数,这样应用程序进程就创建完成了。

3.Binder线程池启动过程

我们首先来看RuntimeInit类的zygoteInit函数,如下所示
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");redirectLogStreams();commonInit();nativeZygoteInit();//1applicationInit(targetSdkVersion, argv, classLoader);}

注释1处会在新创建的应用程序进程中创建Binder线程池,来查看nativeZygoteInit函数:

 private static final native void nativeZygoteInit();

很明显nativeZygoteInit是一个jni方法,它对应的函数是什么呢。在 AndroidRuntime.cpp的JNINativeMethod数组中我们得知它对应的函数是com_android_internal_os_RuntimeInit_nativeZygoteInit,如下所示。
frameworks/base/core/jni/AndroidRuntime.cpp

static const JNINativeMethod gMethods[] = {{ "nativeFinishInit", "()V",(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },{ "nativeZygoteInit", "()V",(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },{ "nativeSetExitWithoutCleanup", "(Z)V",(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

接着来查看 com_android_internal_os_RuntimeInit_nativeZygoteInit函数:
frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}

gCurRuntime是在AndroidRuntime初始化就创建的。如下所示。
frameworks/base/core/jni/AndroidRuntime.cpp

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :mExitWithoutCleanup(false),mArgBlockStart(argBlockStart),mArgBlockLength(argBlockLength)
{...gCurRuntime = this;
}

在Android系统启动流程(二)解析Zygote进程启动过程这篇文章我们得知AppRuntime继承AndroidRuntime,AppRuntime创建时就会调用AndroidRuntime的构造函数,gCurRuntime就会被初始化,它指向的是AppRuntime,因此我们来查看AppRuntime的onZygoteInit函数,AppRuntime的实现在app_main.cpp中,如下所示。
frameworks/base/cmds/app_process/app_main.cpp

 virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");proc->startThreadPool();}

最后一行会调用ProcessState的startThreadPool函数:
frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::startThreadPool()
{AutoMutex _l(mLock);if (!mThreadPoolStarted) {mThreadPoolStarted = true;spawnPooledThread(true);}
}

支持Binder通信的进程中都有一个ProcessState类,它里面有一个mThreadPoolStarted 变量,来表示Binder线程池是否已经被启动过,默认值为false。在每次调用这个函数时都会先去检查这个标记,从而确保Binder线程池只会被启动一次。如果Binder线程池未被启动则设置mThreadPoolStarted为true,最后调用spawnPooledThread函数来创建线程池中的第一个线程,也就是线程池的main线程,如下所示。
frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::spawnPooledThread(bool isMain)
{if (mThreadPoolStarted) {String8 name = makeBinderThreadName();ALOGV("Spawning new pooled thread, name=%s\n", name.string());sp<Thread> t = new PoolThread(isMain);t->run(name.string());//1}
}

可以看到Binder线程为一个PoolThread。注释1调用PoolThread的run函数来启动一个启动一个新的线程。来查看PoolThread类里做了什么:
frameworks/native/libs/binder/ProcessState.cpp

class PoolThread : public Thread
{
..
protected:virtual bool threadLoop(){IPCThreadState::self()->joinThreadPool(mIsMain);//1return false;}const bool mIsMain;
};

PoolThread类继承了Thread类。注释1处会将调用IPCThreadState的joinThreadPool函数,将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,这样新创建的应用程序进程就支持Binder进程间通信了,Binder线程池启动过程就讲到这,接下来我们来学习消息循环创建过程。

4.消息循环创建过程

首先我们回到上篇最后讲到的RuntimeInit的invokeStaticMain函数,代码如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

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

invokeStaticMain函数在上篇已经讲过,这里不再赘述,主要是看最后一行,会抛出一个MethodAndArgsCaller异常,这个异常会被ZygoteInit的main函数捕获,如下所示。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  public static void main(String argv[]) {...try {...} catch (MethodAndArgsCaller caller) {caller.run();//1} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}

注释1处捕获到MethodAndArgsCaller 时会执行caller的run函数,如下所示。
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

 public static class MethodAndArgsCaller extends Exceptionimplements Runnable{private final Method mMethod;private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {mMethod.invoke(null, new Object[] { mArgs });//1} catch (IllegalAccessException ex) {throw new RuntimeException(ex);}...throw new RuntimeException(ex);}}}

根据上一篇文章我们得知,mMethod指的就是ActivityThread的main函数,mArgs 指的是应用程序进程的启动参数。在注释1处调用ActivityThread的main函数,代码如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

 public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");SamplingProfilerIntegration.start();
...Looper.prepareMainLooper();//1ActivityThread thread = new ActivityThread();//2thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();//3throw new RuntimeException("Main thread loop unexpectedly exited");}

注释1处在当前应用程序进程中创建消息循环,注释2处创建ActivityThread,注释3处调用Looper的loop,使得Looper开始工作,开始处理消息。可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,用来方便的使用Android的消息处理机制。


欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。

Android应用程序进程启动过程相关推荐

  1. Android应用程序进程启动过程的源代码分析(1)

    Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实 ...

  2. Android应用程序进程启动过程的源代码分析(2)

      Step 5. ZygoteInit.runSelectLoopMode         这个函数定义在frameworks/base/core/java/com/android/internal ...

  3. android 启动app过程,应用程序进程启动过程

    原标题:应用程序进程启动过程 作者:慕涵盛华 链接:https://www.jianshu.com/p/b158615cc2ad 一.背景 首先注意的是:这里要说的是应用程序进程的启动过程,而不是应用 ...

  4. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  5. 从源码角度看Android系统Zygote进程启动过程

    在Android系统中,DVM.ART.应用程序进程和SystemServer进程都是由Zygote进程创建的,因此Zygote又称为"孵化器".它是通过fork的形式来创建应用程 ...

  6. 应用程序进程启动过程

    --摘自<Android进阶解密> 1.AMS在启动应用程序时会检查者应用程序需要的应用进程是否存在,不存在就会请求Zygote进程启动需要的应用程序进程 2.Zygote的Java框架层 ...

  7. [日更-2019.4.26、27、28] cm-14.1 Android系统启动过程分析(四)-应用程序进程启动过程...

    2019独角兽企业重金招聘Python工程师标准>>> 声明 前阶段在项目中涉及到了Android系统定制任务,Android系统定制前提要知道Android系统是如何启动的: 本文 ...

  8. Android应用程序进程启动流程

    在学习应用程序进程启动流程前,先要弄清楚系统启动流程,如果有不清楚的同学,建议先看下以前博主的文章: Android系统启动(上篇)_AD钙奶-lalala的博客-CSDN博客 Android系统启动 ...

  9. cm-14.1 Android系统启动过程分析(8)-应用程序进程启动过程

    文章目录 声明 0 写在前面 1 什么应用程序进程? 2 应用程序进程的启动过程 2.1 AMS发送启动应用程序进程请求 2.2 Zygote接收AMS的请求并创建应用程序进程 3 启动线程池 4 创 ...

最新文章

  1. Mask-RCNN技术解析
  2. 百万年薪挖了个P8程序员,难道是“水货”?
  3. modbus3-关于Modicon Modbus Protocol和modscan32
  4. 提前祝大家十一中秋节快乐
  5. 电子计算机场地通用规范_最全的视频监控系统施工规范要求
  6. 迭代器 in C++
  7. JS的一些时间获取和计算公用方法封装
  8. python画3D图
  9. Excel将汉字与英文分开
  10. c语言字符二维数组指针赋值,C语言之二维数组与指针
  11. mysql heartbeat_mysql管理工具之pt-heartbeat
  12. Python defaultdict() 的理解
  13. js切换图片会闪动_js 特效 当鼠标经过的时候 图片闪一下光
  14. 火车头免登录php代码,福利|火车采集器免登陆发布接口集合
  15. 手机直播系统,仿映客直播程序项目需求
  16. 什么是自适应布局?什么是响应式布局?他们的区别是什么?
  17. Windows8内核模式下开发NDIS应用 NDIS Filter讲解
  18. WIN7下创建ODBC数据源到SQL Server的新数据源
  19. P3214 [HNOI2011] 卡农 题解
  20. Vue 中使用图片查看器 v-viewer

热门文章

  1. 程序员面试题精选100题(59)-字符串的组合[算法]
  2. Spark编程指南(Python版)
  3. Machine Learning week 7 quiz: programming assignment-Support Vector Machines
  4. Norse Attack Map网络攻击实时监测地图
  5. 编程之美-寻找最大的k个数
  6. Puppet的一些奇技淫巧
  7. PHP中使用ActiveMQ实现消息队列
  8. Open ROADS Community首次正式会议在新加坡顺利召开
  9. linux c:关联变量的双for循环
  10. Criteria查询之分页显示数据