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

2020-06-09  本文已影响0人  杨0612

分析从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<String> argsForZygote = new ArrayList<String>();

            // --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<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> 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过一些常用的资源(常用类、常用库、常用资源),应用进程无需再加载。

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

上一篇下一篇

猜你喜欢

热点阅读