源码分析->应用进程启动过程

分析从fork进程到Application onCreate执行的过程。

源码分析基于Android 23

1.大体过程

1.1 在Launch点击按钮启动A应用, Launch应用与AMS之间是binder通信;
1.2 AMS向Zygote进程请求创建A应用进程,AMS与Zygote之间是Socket通信;
1.3 Zygote通过fork创建A应用进程,并调用ActivityThread.main方法;
1.4 ActivityThread.main()中创建ApplicationThread并注册到AMS,A应用与AMS之间是binder通信;
1.5 AMS请求A应用执行Application onCreate方法,AMS与A应用之间是binder通信。

大致流程.png
2.源码分析
我们知道,在Launch点击按键启动A应用,将触发Activity.startActivity,中间经过很多调用,我们关注最终会调到ActivityStackSupervisor.startSpecificActivityLocked

该方法是启动进程的入口,主要工作:
(1)getProcessRecordLocked,通过进程名获取ProcessRecord;
(2)如果进程启动,则if (app != null && app.thread != null)条件成立,realStartActivityLocked通过跨进程调用启动A应用;
(3)如果进程没有启动,则mService.startProcessLocked,请求AMS启动进程,我们跟进mService.startProcessLocked方法;

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {//进程启动了
            try {
                ......
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        }
        //进程没有启动
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
上述的startProcessLocked最终会调到
ActivityManagerService.startProcessLocked

主要工作:
(1) entryPoint赋值为android.app.ActivityThread,这里就相当熟悉了,后面会通过反射来调用它的main方法;
(2) 调用Process.start来创建进程,返回结果为startResult ,我们跟进去这个方法看看;

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
           ......
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
             ......
            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);
             ......
    }
Process.start->Process.startViaZygote

主要工作:
(1)配置虚拟机的参数,包括ActivityThread的全类名;
(2)openZygoteSocketIfNeeded会调用ZygoteState.connect与Zygote进程建立Socket连接;
(3)zygoteSendArgsAndGetResult,socket连接成功,则发送数据。

 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) {
            ArrayList argsForZygote = new ArrayList();

            // --runtime-args, --setuid=, --setgid=,
            // and --setgroups= must go first
            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");
            }
            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_JIT) != 0) {
                argsForZygote.add("--enable-jit");
            }
            if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
                argsForZygote.add("--generate-debug-info");
            }
            if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                argsForZygote.add("--enable-assert");
            }
            if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
                argsForZygote.add("--mount-external-default");
            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
                argsForZygote.add("--mount-external-read");
            } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
                argsForZygote.add("--mount-external-write");
            }
            argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
             ......
            argsForZygote.add(processClass);//ActivityThread的全类名
           ......
            zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),             argsForZygote);
           ......
            return ;

        }
    }
Socket的服务端在ZygoteInit类中,

(1)runSelectLoop,接收请求由ZygoteConnection.runOnce来处理,我们跟进去看看;
(2)巧妙地利用异常来反射调用ActivityThread.main,MethodAndArgsCaller 异常是封装了反射调用ActivityThread.main。

public static void main(String argv[]) {
            ......
            runSelectLoop(abiList); 
            ......
        } catch (MethodAndArgsCaller caller) {
            caller.run();  //巧妙的利用异常处理,来反射执行ActivityThread.main()
        } 
        ......
    }
ZygoteConnection.runOnce->ZygoteConnection.forkAndSpecialize

主要工作:
(1)Zygote.forkAndSpecialize,内部通过native方法fork进程;
(2)handleChildProc,内部调用RuntimeInit.zygoteInit,我们跟进去看看;

 boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
            ......
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
            ......
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            ......
  }
RuntimeInit.zygoteInit

主要工作:
(1)nativeZygoteInit,启动binder机制:打开binder驱动,映射内存,注册binder线程,进入binder looper;
(2)applicationInit,内部调用RuntimeInit.invokeStaticMain;

   public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ......
        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }
RuntimeInit.invokeStaticMain

主要的工作:
(1)反射方法的校验,类是否存在、方法是否存在、方法是否静态以及public;
(2)最后抛出一个异常ZygoteInit.MethodAndArgsCaller,回到上述的ZygoteInit.main。

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

        try {
            cl = Class.forName(className, true, classLoader);
        } 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 });
        } 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 ZygoteInit.MethodAndArgsCaller(m, argv);
    }
ZygoteInit.MethodAndArgsCaller.run

主要工作:
通过反射来调用ActivityThread.main;

public void run() {
      ......
     mMethod.invoke(null, new Object[] { mArgs });
      ......
}

至此,启动工作转到了ActivityThread.main。

ActivityThread.main()

主要工作:
(1) Looper.prepareMainLooper(),初始化主线程消息队列;
(2)构造ActivityThread,调用attach方法,其中包括把ApplicationThread注册到AMS;
(3)Looper.loop(),启动消息队列;

public static void main(String[] args) {
        ......
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ......
        Looper.loop();
        ......
    }
}
ActivityThread.attach()

主要工作:
mgr.attachApplication(mAppThread),告知AMS,App启动完成。mAppThread是一个Binder对象,是AMS与App通信的入口;

private void attach(boolean system) {
            ......
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ......
    }
ActivityManagerService.attachApplication->ActivityManagerService.attachApplicationLocked

主要工作:
跨进程调用 thread.bindApplication,thread是ApplicationThread类型;

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
            ......
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            ......
            if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            ......
    }
ApplicationThread.bindApplication

主要工作:
sendMessage(H.BIND_APPLICATION, data),将任务转到主线程,会调到handleBindApplication方法。

        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map services,
                Bundle coreSettings) {
            ......
            AppBindData data = new AppBindData();
            ......
            sendMessage(H.BIND_APPLICATION, data);
        }
ActivityThread.handleBindApplication

主要工作:
(1)cl.loadClass(data.instrumentationName.getClassName()).newInstance(),通过反射实例化Instrumentation,这是进程单例;
(2)data.info是LoadeApk类型,对应着一个apk文件,通过makeApplication来构建Application实例,并且会创建ContextImpl通过attachBaseContext赋值给mBase;
(3)callApplicationOnCreate,通过mInstrumentation来调用Application onCreate方法。

 private void handleBindApplication(AppBindData data) {
            ......
        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }//这段代码比较有意思,如果版本是3.1,AsyncTask使用多线程的线程池,包括3.1,否则使用单线程的线程池
            ......
                java.lang.ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            ......
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
            ......
            mInstrumentation.callApplicationOnCreate(app);
}

至此,B应用的Application onCreate方法被调用。

进程启动流程1.png

进程启动流程2.png

3.总结

(1)ActivityStackSupervisor.startSpecificActivityLocked是fork应用进程的入口,如果ProcessRecord以及ApplicationThread都为空则需要fork进程;
(2)Process.start与Zygote进行Socket连接,请求fork进程;
(3)Zygote接收到请求,调用ZygoteConnection.runOnce方法处理for请求;
(4)进程启动以后,把反射调用ActivityThread.main方法封装一个MethodAndArgsCaller异常对象抛出,ZygoteInit捕获异常并执行;
(5)ActivityThread.main启动主线程Looper、构建ActivityThread、进入Looper循环;
(6)ActivityThread.attch向AMS注册ApplicationThread;
(7)AMS跨进程调用ApplicationThread.bindApplication;
(8)ApplicationThread发消息到主线程,ActivityThread创建Application对象,给成员变量mBase赋值,最后调用其onCreate方法。

常见面试题:
1.谈谈你对Application的理解

(1)作用
Application生命周期很长,注意持有短生命对象,导致内存泄漏;
可以在onCreate方法中做一些初始化的工作,但要考虑进程启动速度;
提供全局的上下文,不用担心内存泄漏问题;
多进程应用,就有多个Application实例;
(2)继承关系
继承ContextWrapper,最终是继承Context,有一个mBase全局变量。
(3)调用顺序
构造函数、attachBaseContext、onCreate。

2.进程启动完成的标志

ProcessRecord、ApplicationThread不为空,并且已经向ams注册了ApplicationThread;
、,

3.应用binder机制是什么时候启动的

RuntimeInit.zygoteInit会调用nativeZygoteInit,启动binder机制:打开binder驱动,映射内存,注册binder线程,进入binder looper;

4.为什么采用fork的方式
为了资源复用和加快启动速度,因为Zygote已经preLoad过一些常用的资源(常用类、常用库、常用资源),应用进程无需再加载。

以上分析有不对的地方,请指出,互相学习,谢谢哦!

你可能感兴趣的:(源码分析->应用进程启动过程)