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

原标题:应用程序进程启动过程

作者:慕涵盛华

链接:https://www.jianshu.com/p/b158615cc2ad

一.背景

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

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

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

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

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

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

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

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

1private finalvoidstartProcessLocked(ProcessRecord app, StringhostingType,

2StringhostingNameStr, StringabiOverride, StringentryPoint, String[] entryPointArgs) {

3......

4try{

5try{

6finalintuserId = UserHandle.getUserId(app.uid);

7AppGlobals.getPackageManager.checkPackageStartable(app.info.packageName, userId);

8} catch(RemoteException e) {

9throwe.rethrowAsRuntimeException;

10}

11//获取要创建应用程序进程的用户id

12intuid = app.uid;

13int[] gids = null;

14intmountExternal = Zygote.MOUNT_EXTERNAL_NONE;

15if(!app.isolated) {

16......

17//创建组id和赋值

18if(ArrayUtils.isEmpty(permGids)) {

19gids = newint[ 3];

20} else{

21gids = newint[permGids.length + 3];

22System.arraycopy(permGids, 0, gids, 3, permGids.length);

23}

24gids[ 0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));

25gids[ 1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));

26gids[ 2] = UserHandle.getUserGid(UserHandle.getUserId(uid));

27}

28......

29//ActivityThread

30if(entryPoint == null) entryPoint = "android.app.ActivityThread";

31Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: "+

32app.processName);

33checkTime(startTime, "startProcess: asking zygote to start proc");

34ProcessStartResult startResult;

35if(hostingType.equals( "webview_service")) {

36startResult = startWebView(entryPoint,

37app.processName, uid, uid, gids, debugFlags, mountExternal,

38app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,

39app.info.dataDir, null, entryPointArgs);

40} else{

41//启动应用程序进程

42startResult = Process.start(entryPoint,

43app.processName, uid, uid, gids, debugFlags, mountExternal,

44app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,

45app.info.dataDir, invokeWith, entryPointArgs);

46}

47......

48} catch(RuntimeException e) {

49......

50}

51}

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

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

1private Process.ProcessStartResult startViaZygote( finalStringprocessClass,

2finalStringniceName, finalintuid, finalintgid, finalint[] gids, intdebugFlags, intmountExternal, inttargetSdkVersion, StringseInfo, Stringabi, StringinstructionSet,

3StringappDataDir, StringinvokeWith, String[] extraArgs)throws ZygoteStartFailedEx {

4//创建字符串列表,并将应用进程的启动参数保存在该列表中

5ArrayList< String> argsForZygote = newArrayList< String>;

6argsForZygote.add( "--runtime-args");

7argsForZygote.add( "--setuid="+ uid);

8argsForZygote.add( "--setgid="+ gid);

9if((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {

10argsForZygote.add( "--enable-jni-logging");

11}

12......

13synchronized(mLock) {

14returnzygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);

15}

16}

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

1privatestaticProcess. ProcessStartResult zygoteSendArgsAndGetResult(

2ZygoteState zygoteState, ArrayList args)

3throwsZygoteStartFailedEx {

4try{

5......

6finalBufferedWriter writer = zygoteState.writer;

7finalDataInputStream inputStream = zygoteState.inputStream;

8writer.write(Integer.toString(args.size));

9writer.newLine;

10

11for( inti = 0; i < sz; i++) {

12String arg = args.get(i);

13writer.write(arg);

14writer.newLine;

15}

16writer.flush;

17Process.ProcessStartResult result = newProcess.ProcessStartResult;

18result.pid = inputStream.readInt;

19result.usingWrapper = inputStream.readBoolean;

20if(result.pid < 0) {

21thrownewZygoteStartFailedEx( "fork failed");

22}

23returnresult;

24} catch(IOException ex) {

25zygoteState.close;

26thrownewZygoteStartFailedEx(ex);

27}

28}

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

1privateZygoteState openZygoteSocketIfNeeded(String abi)throwsZygoteStartFailedEx{

2Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

3

4if(primaryZygoteState == null|| primaryZygoteState.isClosed) {

5try{

6//与Zygot进程建立连接 mSocket是一个字符串(private final String mSocket;)

7primaryZygoteState = ZygoteState.connect(mSocket);

8} catch(IOException ioe) {

9thrownewZygoteStartFailedEx( "Error connecting to primary zygote", ioe);

10}

11}

12if(primaryZygoteState.matches(abi)) {

13returnprimaryZygoteState;

14}

15if(secondaryZygoteState == null|| secondaryZygoteState.isClosed) {

16try{

17secondaryZygoteState = ZygoteState.connect(mSecondarySocket);

18} catch(IOException ioe) {

19thrownewZygoteStartFailedEx( "Error connecting to secondary zygote", ioe);

20}

21}

22if(secondaryZygoteState.matches(abi)) {

23returnsecondaryZygoteState;

24}

25thrownewZygoteStartFailedEx( "Unsupported zygote ABI: "+ abi);

26}

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

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

上面提到在Zygote进程中会调用ZygoteServer的runSelectLoop方法来等待AMS的 请求,下面就看一下该方法的具体实现:

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

1voidrunSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller{

2ArrayList fds = newArrayList;

3ArrayList peers = newArrayList;

4fds. add(mServerSocket.getFileDeor);

5peers. add( null);

6while( true) {

7StructPollfd[] pollFds = newStructPollfd[fds.size];

8for( inti = 0; i < pollFds.length; ++i) {

9pollFds[i] = newStructPollfd;

10pollFds[i].fd = fds. get(i);

11pollFds[i].events = ( short) POLLIN;

12}

13try{

14Os.poll(pollFds, -1);

15} catch(ErrnoException ex) {

16thrownewRuntimeException( "poll failed", ex);

17}

18for( inti = pollFds.length - 1; i >= 0; --i) {

19if((pollFds[i].revents & POLLIN) == 0) {

20continue;

21}

22if(i == 0) {

23ZygoteConnection newPeer = acceptCommandPeer(abiList);

24peers. add(newPeer);

25fds. add(newPeer.getFileDesciptor);

26} else{

27boolean done = peers. get(i).runOnce( this);

28if(done) {

29peers. remove(i);

30fds. remove(i);

31}

32}

33}

34}

35}

从上述代码中看出实际上是调用ZygoteConnection的runOnce方法来处理请求数据的,下面就看一下该方法:

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

1booleanrunOnce(ZygoteServer zygoteServer)throwsZygote.MethodAndArgsCaller{

2

3String args[];

4Arguments parsedArgs = null;

5FileDeor[] deors;

6try{

7//获取应用程序进程的启动参数

8args = readArgumentList;

9deors = mSocket.getAncillaryFileDeors;

10} catch(IOException ex) {

11Log.w(TAG, "IOException on command socket "+ ex.getMessage);

12closeSocket;

13returntrue;

14}

15......

16try{

17parsedArgs = newArguments(args);

18......

19//创建应用程序进程

20pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,

21parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,

22parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,

23parsedArgs.appDataDir);

24} catch(ErrnoException ex) {

25......

26}

27try{

28if(pid == 0) {

29// in child

30zygoteServer.closeServerSocket;

31IoUtils.closeQuietly(serverPipeFd);

32serverPipeFd = null;

33//处理应用程序进程

34handleChildProc(parsedArgs, deors, childPipeFd, newStderr);

35returntrue;

36} else{

37// in parent...pid of < 0 means failure

38IoUtils.closeQuietly(childPipeFd);

39childPipeFd = null;

40returnhandleParentProc(pid, deors, serverPipeFd, parsedArgs);

41}

42} finally{

43IoUtils.closeQuietly(childPipeFd);

44IoUtils.closeQuietly(serverPipeFd);

45}

46}

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

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

1publicstaticfinalvoidzygoteInit(inttargetSdkVersion, String[] argv,

2ClassLoader classLoader)throwsZygote.MethodAndArgsCaller {

3if(RuntimeInit.DEBUG) {

4Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");

5}

6Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");

7RuntimeInit.redirectLogStreams;

8RuntimeInit.commonInit;

9//创建Binder线程池

10ZygoteInit.nativeZygoteInit;

11//最终会调用ActivityThread的main方法(应用程序进程的入口方法)

12RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);

13}

该方法运行在应用程序进程中,主要做了两件事情:1.创建Binder线程池(nativeZygoteInit);2.执行ActivityThread的main方法(RuntimeInit.applicationInit)。RuntimeInit.applicationInit方法中会调用

invokeStaticMain(args.startClass, args.startArgs, classLoader);,第一个传入的参数就是上面提到的android.app.ActivityThread。/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

1private staticvoidinvokeStaticMain( StringclassName, String[] argv, ClassLoader classLoader)

2throws Zygote.MethodAndArgsCaller {

3Class> cl;

4

5try{

6//通过反射获取ActivityThread类

7cl = Class.forName(className, true, classLoader);

8} catch(ClassNotFoundException ex) {

9thrownewRuntimeException(

10"Missing class when invoking static main "+ className,

11ex);

12}

13Method m;

14try{

15//获取ActivityThread的main方法

16m = cl.getMethod( "main", newClass[] { String[]. class});

17} catch(NoSuchMethodException ex) {

18thrownewRuntimeException(

19"Missing static main on "+ className, ex);

20} catch(SecurityException ex) {

21thrownewRuntimeException(

22"Problem getting static main on "+ className, ex);

23}

24

25intmodifiers = m.getModifiers;

26if(! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {

27thrownewRuntimeException(

28"Main method is not public and static on "+ className);

29}

30//抛出异常,注意传入的参数

31thrownewZygote.MethodAndArgsCaller(m, argv);

32}

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

1publicstaticvoidmain(String argv[]){

2......

3} catch(Zygote.MethodAndArgsCaller caller) {

4caller.run;

5} catch(Throwable ex) {

6Log.e(TAG, "System zygote died with exception", ex);

7zygoteServer.closeServerSocket;

8throwex;

9}

10}

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

1public voidrun {

2try{

3//反射调用方法

4mMethod.invoke( null, newObject[] { mArgs });

5} catch(IllegalAccessException ex) {

6thrownewRuntimeException(ex);

7} catch(InvocationTargetException ex) {

8Throwable cause = ex.getCause;

9if(cause instanceofRuntimeException) {

10throw(RuntimeException) cause;

11} elseif(cause instanceofError) {

12throw( Error) cause;

13}

14thrownewRuntimeException(ex);

15}

16}

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

/frameworks/base/core/java/android/app/ActivityThread.java

1publicstaticvoidmain(String[] args){

2......

3//创建主线程Looper

4Looper.prepareMainLooper;

5ActivityThread thread = newActivityThread;

6thread.attach( false);

7//创建Handler

8if(sMainThreadHandler == null) {

9sMainThreadHandler = thread.getHandler;

10}

11if( false) {

12Looper.myLooper.setMessageLogging( new

13LogPrinter(Log.DEBUG, "ActivityThread"));

14}

15// End of event ActivityThreadMain.

16Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

17//开启消息轮询

18Looper.loop;

19thrownewRuntimeException( "Main thread loop unexpectedly exited");

20}

关注公众号,回复"flutter"获取flutter视频教程返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值