Android应用框架之应用启动过程详解
在Android的应用框架中,ActivityManagerService是非常重要的一个组件,尽管名字叫做ActivityManagerService,但通过之前的博客介绍,我们知道,四大组件的创建都是有AMS来完成的,其实不仅是应用程序中的组件,连Android应用程序本身也是AMS负责启动的。AMS本身运行在一个独立的进程中,当系统决定要在一个新的进程中启动一个Activity或者Service时就会先启动这个进程。而AMS启动进程的过程是从startProcessLocked启动的。
1.ActivityManagerService.startProcessLocked
publicfinalclassActivityManagerServiceextendsActivityManagerNative implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{ ...... privatefinalvoidstartProcessLocked(ProcessRecordapp, StringhostingType,StringhostingNameStr){ ...... try{ intuid=app.info.uid; int[]gids=null; try{ gids=mContext.getPackageManager().getPackageGids( app.info.packageName); }catch(PackageManager.NameNotFoundExceptione){ ...... } ...... intdebugFlags=0; ...... intpid=Process.start("android.app.ActivityThread", mSimpleProcessManagement?app.processName:null,uid,uid, gids,debugFlags,null); ...... }catch(RuntimeExceptione){ ...... } } ...... }
可以看到,函数会调用Process.start函数来创建一个进程,其中第一个参数”android.app.ActivityThread”是需要加载的类,而在完成这个类的加载之后就会运行ActivityThread.main函数。
2.Process.start
publicclassProcess{ ...... publicstaticfinalintstart(finalStringprocessClass, finalStringniceName, intuid,intgid,int[]gids, intdebugFlags, String[]zygoteArgs) { if(supportsProcesses()){ try{ returnstartViaZygote(processClass,niceName,uid,gid,gids, debugFlags,zygoteArgs); }catch(ZygoteStartFailedExex){ ...... } }else{ ...... return0; } } ...... }
这个函数最后会调用startViaZygote来创建进程,而Zygote正是Android孵化进程的服务,所有的进程都是通过Zygotefork出来的,所以这里创建进程的任务又落到了Zygote头上了。
3.Process.startViaZygote
publicclassProcess{ ...... privatestaticintstartViaZygote(finalStringprocessClass, finalStringniceName, finalintuid,finalintgid, finalint[]gids, intdebugFlags, String[]extraArgs) throwsZygoteStartFailedEx{ intpid; synchronized(Process.class){ ArrayList<String>argsForZygote=newArrayList<String>(); //--runtime-init,--setuid=,--setgid=, //and--setgroups=mustgofirst argsForZygote.add("--runtime-init"); argsForZygote.add("--setuid="+uid); argsForZygote.add("--setgid="+gid); if((debugFlags&Zygote.DEBUG_ENABLE_SAFEMODE)!=0){ argsForZygote.add("--enable-safemode"); } if((debugFlags&Zygote.DEBUG_ENABLE_DEBUGGER)!=0){ argsForZygote.add("--enable-debugger"); } if((debugFlags&Zygote.DEBUG_ENABLE_CHECKJNI)!=0){ argsForZygote.add("--enable-checkjni"); } if((debugFlags&Zygote.DEBUG_ENABLE_ASSERT)!=0){ argsForZygote.add("--enable-assert"); } //TODOoptionallyenabledebuger //argsForZygote.add("--enable-debugger"); //--setgroupsisacomma-separatedlist if(gids!=null&&gids.length>0){ StringBuildersb=newStringBuilder(); sb.append("--setgroups="); intsz=gids.length; for(inti=0;i<sz;i++){ if(i!=0){ sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if(niceName!=null){ argsForZygote.add("--nice-name="+niceName); } argsForZygote.add(processClass); if(extraArgs!=null){ for(Stringarg:extraArgs){ argsForZygote.add(arg); } } pid=zygoteSendArgsAndGetPid(argsForZygote); } } ...... }
函数里面最为重要的工作就是组装argsForZygote参数,这些参数将告诉Zygote具体的启动选项,例如”–runtime-init”就表示要为新启动的运行程序初始化运行库。然后调用zygoteSendAndGetPid函数进一步操作。
4.Process.zygoteSendAndGetPid
publicclassProcess{ ...... privatestaticintzygoteSendArgsAndGetPid(ArrayList<String>args) throwsZygoteStartFailedEx{ intpid; openZygoteSocketIfNeeded(); try{ /** *Seecom.android.internal.os.ZygoteInit.readArgumentList() *Presentlythewireformattothezygoteprocessis: *a)acountofarguments(argc,inessence) *b)anumberofnewline-separatedargumentstringsequaltocount * *Afterthezygoteprocessreadstheseitwillwritethepidof *thechildor-1onfailure. */ sZygoteWriter.write(Integer.toString(args.size())); sZygoteWriter.newLine(); intsz=args.size(); for(inti=0;i<sz;i++){ Stringarg=args.get(i); if(arg.indexOf('\n')>=0){ thrownewZygoteStartFailedEx( "embeddednewlinesnotallowed"); } sZygoteWriter.write(arg); sZygoteWriter.newLine(); } sZygoteWriter.flush(); //Shouldtherebeatimeoutonthis? pid=sZygoteInputStream.readInt(); if(pid<0){ thrownewZygoteStartFailedEx("fork()failed"); } }catch(IOExceptionex){ ...... } returnpid; } ...... } 这里的sZygoteWriter
是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的。而这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。这个类会返回一个ZygoteConnection实例,并执行ZygoteConnection的runOnce函数。
5.ZygoteConnection.runOnce
classZygoteConnection{ ...... booleanrunOnce()throwsZygoteInit.MethodAndArgsCaller{ Stringargs[]; ArgumentsparsedArgs=null; FileDescriptor[]descriptors; try{ args=readArgumentList(); descriptors=mSocket.getAncillaryFileDescriptors(); }catch(IOExceptionex){ ...... returntrue; } ...... /**thestderrofthemostrecentrequest,ifavail*/ PrintStreamnewStderr=null; if(descriptors!=null&&descriptors.length>=3){ newStderr=newPrintStream( newFileOutputStream(descriptors[2])); } intpid; try{ parsedArgs=newArguments(args); applyUidSecurityPolicy(parsedArgs,peer); applyDebuggerSecurityPolicy(parsedArgs); applyRlimitSecurityPolicy(parsedArgs,peer); applyCapabilitiesSecurityPolicy(parsedArgs,peer); int[][]rlimits=null; if(parsedArgs.rlimits!=null){ rlimits=parsedArgs.rlimits.toArray(intArray2d); } pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags,rlimits); }catch(IllegalArgumentExceptionex){ ...... }catch(ZygoteSecurityExceptionex){ ...... } if(pid==0){ //inchild handleChildProc(parsedArgs,descriptors,newStderr); //shouldneverhappen returntrue; }else{/*pid!=0*/ //inparent...pidof<0meansfailure returnhandleParentProc(pid,descriptors,parsedArgs); } } ...... }
真正创建进程的代码在Zygote.forkAndSpecialize,通过Zygote来fork出一个新的进程作为应用进程。fork函数会有两个返回,其中一个在父进程,一个在子进程,其中自进程的进程号会为0,所以按照上面的代码,这里会执行handleChildProc。
6.ZygoteConnection.handleChildProc
classZygoteConnection{ ...... privatevoidhandleChildProc(ArgumentsparsedArgs, FileDescriptor[]descriptors,PrintStreamnewStderr) throwsZygoteInit.MethodAndArgsCaller{ ...... if(parsedArgs.runtimeInit){ RuntimeInit.zygoteInit(parsedArgs.remainingArgs); }else{ ...... } } ...... }
因为在创建的时候传入了“–runtime-init”,所以这里会运行RuntimeInit.zygoteInit。
publicclassRuntimeInit{ ...... publicstaticfinalvoidzygoteInit(String[]argv) throwsZygoteInit.MethodAndArgsCaller{ //TODO:Doingthishereworks,butitseemskindofarbitrary.Find //abetterplace.Thegoalistosetitupforapplications,butnot //toolslikeam. System.setOut(newAndroidPrintStream(Log.INFO,"System.out")); System.setErr(newAndroidPrintStream(Log.WARN,"System.err")); commonInit(); zygoteInitNative(); intcurArg=0; for(/*curArg*/;curArg<argv.length;curArg++){ Stringarg=argv[curArg]; if(arg.equals("--")){ curArg++; break; }elseif(!arg.startsWith("--")){ break; }elseif(arg.startsWith("--nice-name=")){ StringniceName=arg.substring(arg.indexOf('=')+1); Process.setArgV0(niceName); } } if(curArg==argv.length){ Slog.e(TAG,"MissingclassnameargumenttoRuntimeInit!"); //lettheprocessexit return; } //Remainingargumentsarepassedtothestartclass'sstaticmain StringstartClass=argv[curArg++]; String[]startArgs=newString[argv.length-curArg]; System.arraycopy(argv,curArg,startArgs,0,startArgs.length); invokeStaticMain(startClass,startArgs); } ...... }
这里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step1中传进来的”android.app.ActivityThread”值,表示要执行android.app.ActivityThread类的main函数。
7.Zygote.invokeStaticMain
publicclassZygoteInit{ ...... staticvoidinvokeStaticMain(ClassLoaderloader, StringclassName,String[]argv) throwsZygoteInit.MethodAndArgsCaller{ Class<?>cl; try{ cl=loader.loadClass(className); }catch(ClassNotFoundExceptionex){ ...... } Methodm; try{ m=cl.getMethod("main",newClass[]{String[].class}); }catch(NoSuchMethodExceptionex){ ...... }catch(SecurityExceptionex){ ...... } intmodifiers=m.getModifiers(); ...... /* *ThisthrowgetscaughtinZygoteInit.main(),whichresponds *byinvokingtheexception'srun()method.Thisarrangement *clearsupallthestackframesthatwererequiredinsetting *uptheprocess. */ thrownewZygoteInit.MethodAndArgsCaller(m,argv); } ...... }
从代码中可以看到,通过ClassLoader加载对应的android.app.ActivityThread类,然后再获取到对应的main函数句柄,最后调用该类的main函数。不过这里的调用方式比较有意思,不知直接调用,而是通过抛出一个异常。这样做的方式是为了清空堆栈,让系统认为新进程是从ActivityThread的main函数开始的。
8.ActivityThread.main
publicfinalclassActivityThread{ ...... publicstaticfinalvoidmain(String[]args){ SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if(sMainThreadHandler==null){ sMainThreadHandler=newHandler(); } ActivityThreadthread=newActivityThread(); thread.attach(false); if(false){ Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG,"ActivityThread")); } Looper.loop(); if(Process.supportsProcesses()){ thrownewRuntimeException("Mainthreadloopunexpectedlyexited"); } thread.detach(); Stringname=(thread.mInitialApplication!=null) ?thread.mInitialApplication.getPackageName() :"<unknown>"; Slog.i(TAG,"Mainthreadof"+name+"isnowexiting"); } ...... }
从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象,然后进入消息循环中,这样,我们以后就可以在这个进程中启动Activity或者Service了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。