App的启动过程

终究还是要自己写一遍才能记忆深刻,事实证明好记性不如烂笔头真的非常有道理,本文转载自https://blog.csdn.net/hzwailll/article/details/85339714
这篇文章,大神的描述已经非常清晰,但是自己在阅读学习的时候,仍然有一部分不明确,本文在转载原文的基础上,进行了再解释,如果有版权问题,请直接@作者。

概述

从点击桌面应用图标,到应用显示这个过程到底做了什么,今天我们来详细的分析一下。
本文主要分析以下问题:
Application在哪里赋值的
主线程Looper的初始化
主线程Handler的初始化
系统启动过程
App 启动过程
Activity的创建和启动

ActivityThread

ActivityThread本身不是一个线程,但是他代表主线程,这里面的main方法,是一个app的真正入口。

/**
* This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
* manager requests.
 *
 * {@hide}
 */
public final class ActivityThread

上面是ActivityThread的定义,下面则是main方法,也就是所有的app程序运行的起点。

 public static void main(String[] args) {


//此处调用Looper中的prepareMainLooper方法,和一个普通线程使用过程中调用looper.prepare是一个作用,实际上源码中调用的就是Looper.prepare()方法,由此可知启动即调用,所以主线程无需调用prepare方法。
Looper.prepareMainLooper();

//此处new一个ActivityThread方法,下面调用attach(),attach是一个核心方法,我们接下来看他的源码
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
	//这个地方是对主线程handler的初始化
        sMainThreadHandler = thread.getHandler();
    }
    .......................
}

attach方法

ActivityThread中的attach方法完成了application的初始化操作,分析源码如下:

干扰代码我们暂时忽略掉,重点是mgr.attachApplication这一行代码:

 private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManager.getService();
        try {
        //关键中的关键,我们往下继续跟踪
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // Watch for getting close to heap limit.
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
               。。。。。。
            }
        });
    } else {
   .......................
    }
}

这个时候你可能看不到IActivityManager类的定义,不用担心,我们直接查看ActivityManagerService类,

@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

ActivityManagerService中的方法:
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

*******此处转载大牛的原话,后面会把转载连接发出来
这里的个人理解是:在每个ActivityThread(APP)被创建的时候,
都需要向ActivityManagerService绑定(或者说是向远程服务AMS注册自己),
用于AMS管理ActivityThread中的所有四大组件的生命周期。

上述AMS的代码中attachApplicationLocked方法比较复杂,主要功能有两个,详见注释,AMS中的方法,主要功能有以下两步

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    ...
    主要用于创建Application,用调用onCreate方法
	thread.bindApplication(...);
	...
	主要用于创建Activity
    if (mStackSupervisor.attachApplicationLocked(app)) {
        ...
    }
}

thread.bindApplication:主要用于创建Application,这里的thread对象是ApplicationThread在AMS中的代理对象,所以这里的bindApplication方法最终会调用ApplicationThread.bindApplication()方法,该方法会向ActivityThread的消息对应发送BIND_APPLICATION的消息,消息的处理最终会调用Application.onCreate()方法,这也说明Application.onCreate()方法的执行时机比任何Activity.onCreate()方法都早。

ActivityThread中的bindApplication方法
public final void bindApplication(...) {
    ...
    该消息的处理,会调用handleBindApplication方法
    sendMessage(H.BIND_APPLICATION, data);
}
ActivityThread中的handleBindApplication方法
private void handleBindApplication(AppBindData data) {
    ...
    try {
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
        }
    } finally {
    }
}
    
LoadedApk中的方法,用于创建Application
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
    如果存在Application的实例,则直接返回,这也说明Application是个单例
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;
    ...这里通过反射初始化Application

    if (instrumentation != null) {
        try {
            调用Application的onCreate方法
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
        }
    }
    return app;
}

mStackSupervisor.attachApplicationLocked(app):用于创建Activity,mStackSupervisor是AMS的成员变量,为Activity堆栈管理辅助类实例,该方法最终会调用ApplicationThread类的scheduleLaunchActivity方法,该方法也是类似于第一步,向ActivityThread的消息队列发送创建Activity的消息,最终在ActivityThread中完成创建Activity的操作。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    ...
    if (realStartActivityLocked(hr, app, true, true)) {
        ...
    }          
    ...
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    try {
        调用ApplicationThread的scheduleLaunchActivity用于启动一个Activity
        app.thread.scheduleLaunchActivity(...);
    } catch (RemoteException e) {
    }
}

ApplicationThread的scheduleLaunchActivity方法会向ActivityThread发送LAUNCH_ACTIVITY信息,用于启动一个Activity,该消息的处理会调用ActivityThread的handleLaunchActivity方法,最终启动一个Activity

以上就是从ActivityThread的main方法执行到Activity的创建之间的流程,至于ActivityThread的main方法执行时机,以及执行前的流程和Activity的具体创建过程。

App的启动过程

app启动过程可以总结为一下几个流程:

加载bootLoader-》内核初始化-》启动init进程-》init进程fork处Zygote进程-》Zygote进程fork出SystemService进程
在这里插入图片描述

系统中所有的进程都是有Zygote(孵化器)进程fork出来的。

SystemServer进程是系统进程,很多系统服务,例如ActivityManagerService,PackageManagerService,WindowManagerService都存在该进程被创建后启动。

ActivityManagerServices,是一个服务端对象,负责所有的Activity的生命周期,AMS通过Binder与Activity进行通信,而AMS与Zygote之间通过Socket进行通信。

ActivityThread,UI线程,它的main()方法是App的真正入口。

ApplicationThread,一个实现了IBinder接口的ActivityThread内部类,用于ActivityThread和AMS的所在进程间通信。

Instrumentation,是ActivityThread的一个工具类,在ActivityThread中初始化,一个进程只存在一个INstrumentation对象,所以在每个Activity初始化时候,会通过Activity的Attach方法,将该引用传递给Activity,Activity所有生命周期的方法都由该类执行。

APP的启动过程

APP的启动,我们使用一张图来说明这个启动过程,顺便也总结下上面所说的ActivityThread的main方法执行到Activity的创建之间的流程。图是从网上盗的…

在这里插入图片描述
1、点击桌面App图标时候,Launcher的startActivity通过Binder通信,调用System_server进程中的AMS服务的startActivity方法,发起启动请求。

2、system_server进程收到请求之后,向Zygote进程发送创建进程请求。

3、Zygote进程fork出App进程之后,执行ActivityThread的main()方法,创建ActivityThread线程,初始化MainLooper,主线程Handler,同时初始化ApplicationThread用于和Ams通信交互。

4、App进程,通过Binder向system_service进程发起attachApplication请求,这里实际上就是App进程通过Binder调用System_server进程中AMS的attachApplication方法,上面已经分析过,Ams的attachApplication方法作用就是将ApplicationThread对象与AMS绑定。

5、system_server进程在收到attachApplication的请求之后,进行一些准备工作,在通过Binder IPC向app进程发送handBindApplication请求,初始化Applicaion并调用onCreate方法,和scheduleLaunchActivity创建和启动Activity请求。

6、App进程的binder线程(ApplicationThread)在收到请求之后,通过handler向主线程发送BIND_APPLICATION和LANUCH_ACTIVITY消息,这里注意的是AMS和主线程并不直接通信,而是AMS和主线程的内部类ApplicationThread通过Binder通信,ApplicationThread在和主线程通过Handler消息交互。

7、主线程收到Message后,创建Application并调用onCreate方法,并通过反射机制创建目标Activity,并回调Activity.onCreate等方法。

8、至此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染后显示APP主界面。

为什么创建几个进程,Application会被创建几次

在上面学习APP的启动过程中,看源码的同时注意到一个代码,就是主线程Handler在接收到LAUNCH_ACTIVITY创建Activity的消息后,创建Activity的部分代码如下:

主线程Handler接收到创建Activity的消息LAUNCH_ACTIVITY后,最终会调用performLaunchActivity方法
performLaunchActivity方法会通过反射去创建一个Activity,然后会调用Activity的各个生命周期方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        这里是反射创建Activity
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    }

    try {
        这里注意,又调用了一次Application的创建方法,但是前面分析过,Application是个单例,所以这里的实际上是获取Application实例,但是这里为什么会再次调用创建Application的方法呢?
        
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
    } 
    ...
    return activity;
}

在上面的代码中,简单注释了一下在Activity的创建方法中,会再次调用Application的创建方法(第一次调用是在接收到BIND_APPLICATION消息的时候),个人觉得这里再次调用Application的创建方法,除了获取已经存在的Application实例这种情况,另外一种情况还有可能是要创建的这个Activity属于另外一个进程,当去启动这个新进程中的Activity时,会先去创建新进程和Application实例,因为我们知道一个常识:

APP中有几个进程,Application会被创建几次
新进程中所有变量和单例会失效,因为新进程有一块新的内存区域
那么这两点的关系就是,因为新进程中Application实例会为空,所以会再次去创建Application实例,这也就是第一点中我们所说的常识:APP中有几个进程,Application会被创建几次

创建Application的方法
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
    如果存在Application的实例,则直接返回,这也说明Application是个单例
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;
    ...创建Application
    return app;
}

那么依次类推,Service作为四大组件之一,类似于Activity的创建和启动,创建Service的方法中会不会也调用了创建Application的方法(makeApplication方法),答案是肯定的!和Activity的创建类似,当我们调用startService的时候,也是通过Binder向AMS发送创建Service的请求,AMS准备后再向APP进程发送scheduleCreateService的请求,然后主线程handle收到CREATE_SERVICE的消息,调用handleCreateService创建Service的方法。在创建Service的方法handleCreateService中也调用了创建Application的方法,具体代码看源码吧。所以我们也彻底明白了为什么APP中有几个进程,Application会被创建几次,以及Application为什么是个单例。

上面博客内容的补充与再解释:

虽然四大组件service创建的时候,同样会调用makApplication但是上文已经明确,application是一个单例,所以创建sercice的时候只会在      
  if (mApplication != null) {
        return mApplication;
    }

这个地方返回,因此哪怕掉了makeApplication,仍然不会调用下面的application的oncreate方法,只有在创建新的进程的时候,才会从新创建,因此上面的,“App有几个进程,Application会被创建几次”,可以更改为,App中有几个进程,Application中的onCreate就会调用几次,其余service等等的创建虽然会调用makeApplicaiton,但是因为applicaiton是一个单例,所以,并不会重复调用applicaiont的onCreate方法。
原文链接:https://blog.csdn.net/hzwailll/article/details/85339714

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值