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了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。