首页 > 其他分享 >Application创建过程-1

Application创建过程-1

时间:2023-08-14 17:47:16浏览次数:40  
标签:创建 app ContextImpl ActivityThread LoadedApk Application null 过程

 一、概述

system进程和app进程都运行着一个或多个app,每个app都会有一个对应的 Application对象#######(该对象 跟 LoadedApk 一一对应)。下面分别以下两种进程创建Application的过程:

1. system_server进程;

2. app进程;


二、system_server进程

2.1 SystemServer.run

[-> SystemServer.java]

public final class SystemServer {
    private void run() {
        ...
        createSystemContext(); //[见2.2]
        startBootstrapServices(); //开始启动服务
        ...
    }
}

 

2.2 createSystemContext

[-> SystemServer.java]

private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();  //[见2.3]
    mSystemContext = activityThread.getSystemContext();  //[见2.6.1]
    mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}

 

2.3 AT.systemMain

[-> ActivityThread.java]

public static ActivityThread systemMain() {
    ...
    ActivityThread thread = new ActivityThread();  //[见2.4]
    thread.attach(true);  //[见2.5]
    return thread;
}

 

2.4 AT初始化

[-> ActivityThread.java]

public final class ActivityThread {
    //创建ApplicationThread对象
    final ApplicationThread mAppThread = new ApplicationThread();
    final Looper mLooper = Looper.myLooper();
    final H mH = new H();
    //当前进程中首次初始化的app对象
    Application mInitialApplication;
    final ArrayList<Application> mAllApplications;
    //标记当前进程是否为system进程
    boolean mSystemThread = false;
    //记录system进程的ContextImpl对象
    private ContextImpl mSystemContext;

    final ArrayMap<String, WeakReference<LoadedApk>> mPackages;
    static Handler sMainThreadHandler;
    private static ActivityThread sCurrentActivityThread;

    ActivityThread() {
        mResourcesManager = ResourcesManager.getInstance();
    }
}

其中 mInitialApplication 的赋值过程分两种场景:

(1) system_server 进程是由 ActivityThread.attach() 过程赋值;
(2) 普通 app 进程是由是由 ActivityThread.handleBindApplication() 过程赋值;这是进程刚创建后 attach 到 system_server 后, 便会 binder call 到 app 进程来执行该方法.

AT.currentApplication 返回的便是 mInitialApplication 对象。创建完 ActivityThread 对象,接下来执行 attach() 操作。


2.5 AT.attach

[-> ActivityThread.java]

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system; //设置mSystemThread为true
    if (!system) {
        ...
    } else { //system进程才执行该流程
        //创建Instrumentation
        mInstrumentation = new Instrumentation();
        //[见小节2.6]
        ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
        //[见小节2.7]
        mInitialApplication = context.mPackageInfo.makeApplication(true, null);
        //回调onCreate方法[见小节2.5.1]
        mInitialApplication.onCreate();
        ...
    }
}

attach 的主要功能:
(1) 根据 LoadedApk 对象来创建 ContextImpl,对于 system 进程 LoadedApk 对象取值为 mSystemContext;
(2) 初始化 Application 信息。


2.5.1 onCreate

[-> Application.java]

public void onCreate() {
    ... //该方法为空, 一般地都是由其子类所覆写该方法
}

 

2.6 CI.createAppContext

[-> ContextImpl.java]

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    //[见小节2.6.4]
    return new ContextImpl(null, mainThread, packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}

创建 ContextImpl 对象有多种方法,常见的有:

createSystemContext(ActivityThread mainThread)
createAppContext(ActivityThread mainThread, LoadedApk packageInfo)
createApplicationContext(ApplicationInfo application, int flags)
createPackageContext(String packageName, int flags)

此处,packageInfo 是 getSystemContext().mPackageInfo,getSystemContext() 获取的 ContextImpl 对象, 其成员变量 mPackageInfo 便是 LoadedApk 对象。所以先来看看 getSystemContext() 过程。


2.6.1 AT.getSystemContext

public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

单例模式创建 mSystemContext 对象。

2.6.2 CI.createSystemContext

static ContextImpl createSystemContext(ActivityThread mainThread) {
    //创建LoadedApk对象 【见小节2.6.3】
    LoadedApk packageInfo = new LoadedApk(mainThread);
    // 创建ContextImpl【见小节2.6.4】
    ContextImpl context = new ContextImpl(null, mainThread,
            packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
    ...
    return context;
}


2.6.3 LoadedApk初始化

public final class LoadedApk {
    private final ActivityThread mActivityThread;
    private ApplicationInfo mApplicationInfo;
    private Application mApplication;
    final String mPackageName;
    private final ClassLoader mBaseClassLoader;
    private ClassLoader mClassLoader;

    LoadedApk(ActivityThread activityThread) {
        mActivityThread = activityThread; //ActivityThread对象
        mApplicationInfo = new ApplicationInfo(); //创建ApplicationInfo对象
        mApplicationInfo.packageName = "android";
        mPackageName = "android";  //默认包名为"android"
        ...
        mBaseClassLoader = null;
        mClassLoader = ClassLoader.getSystemClassLoader(); //创建ClassLoader
        ...
    }
}

只有一个参数的 LoadedApk 构造方法只有 createSystemContext() 过程才会创建, 其中 LoadedApk 初始化过程会创建 ApplicationInfo 对象,且包名为“android”。 创建完 LoadedApk 对象,接下来创建 ContextImpl 对象。

2.6.4 ContextImpl初始化

class ContextImpl extends Context {
    final ActivityThread mMainThread;
    final LoadedApk mPackageInfo;
    private final IBinder mActivityToken;
    private final String mBasePackageName;
    private Context mOuterContext;
    //缓存Binder服务
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

    private ContextImpl(ContextImpl container, ActivityThread mainThread, LoadedApk packageInfo, IBinder activityToken, UserHandle user, 
            boolean restricted, Display display, Configuration overrideConfiguration, int createDisplayWithId) {
        mOuterContext = this; //ContextImpl对象
        mMainThread = mainThread; // ActivityThread赋值
        mPackageInfo = packageInfo; // LoadedApk赋值
        mBasePackageName = packageInfo.mPackageName; //mBasePackageName等于“android”
        ...
    }
}

首次执行 getSystemContext,会创建 LoadedApk 和 contextImpl 对象,接下来利用刚创建的 LoadedApk 对象来创建新的 ContextImpl 对象。


2.7 makeApplication

[-> LoadedApk.java]

public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
    //保证一个LoadedApk对象只创建一个对应的Application对象
    if (mApplication != null) {
        return mApplication;
    }

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application"; //system_server进程, 则进入该分支
    }

    //创建ClassLoader对象【见小节2.8】
    java.lang.ClassLoader cl = getClassLoader();
    if (!mPackageName.equals("android")) {
        initializeJavaContextClassLoader();  //[见小节2.9]
    }

    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    //创建Application对象[见2.10]
    Application app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);
    ...

    mActivityThread.mAllApplications.add(app);
    mApplication = app; //将刚创建的app赋值给mApplication
    ...
    return app;
}

 

2.8 getClassLoader

[-> LoadedApk.java]

public ClassLoader getClassLoader() {
    synchronized (this) {
        if (mClassLoader != null) {
            return mClassLoader;
        }

        if (mPackageName.equals("android")) {
            if (mBaseClassLoader == null) {
                //创建Classloader对象
                mClassLoader = ClassLoader.getSystemClassLoader();
            } else {
                mClassLoader = mBaseClassLoader;
            }
            return mClassLoader;
        }

        // 当包名不为"android"的情况
        if (mRegisterPackage) {
            //【见小节2.8.1】
            ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
        }

        zipPaths.add(mAppDir);
        libPaths.add(mLibDir);
        apkPaths.addAll(zipPaths);
        ...

        if (mApplicationInfo.isSystemApp()) {
            isBundledApp = true;
            //对于系统app,则添加vendor/lib, system/lib库
            libPaths.add(System.getProperty("java.library.path"));
            ...
        }

        final String zip = TextUtils.join(File.pathSeparator, zipPaths);

        //获取ClassLoader对象【见小节2.8.2】
        mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
                mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
                libraryPermittedPath, mBaseClassLoader);
        return mClassLoader;
    }
}


2.8.1 AMS.addPackageDependency

public void addPackageDependency(String packageName) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        if (callingPid == Process.myPid()) {
            return;
        }
        ProcessRecord proc;
        synchronized (mPidsSelfLocked) {
            //查询的进程
            proc = mPidsSelfLocked.get(Binder.getCallingPid());
        }
        if (proc != null) {
            if (proc.pkgDeps == null) {
                proc.pkgDeps = new ArraySet<String>(1);
            }
            //将目标包名加入到调用者进程的pkgDeps
            proc.pkgDeps.add(packageName);
        }
    }
}


2.8.2 AL.getClassLoader

[-> ApplicationLoaders.java]

public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                              String librarySearchPath, String libraryPermittedPath,
                              ClassLoader parent) {
    //获取父类的类加载器
    ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();

    synchronized (mLoaders) {
        if (parent == null) {
            parent = baseParent;
        }

        if (parent == baseParent) {
            ClassLoader loader = mLoaders.get(zip);
            if (loader != null) {
                return loader;
            }
            //创建PathClassLoader对象
            PathClassLoader pathClassloader = PathClassLoaderFactory.createClassLoader(
                                          zip,
                                          librarySearchPath,
                                          libraryPermittedPath,
                                          parent,
                                          targetSdkVersion,
                                          isBundled);
            mLoaders.put(zip, pathClassloader);
            return pathClassloader;
        }

        PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
        return pathClassloader;
    }
}

 

2.9 initializeJavaContextClassLoader

[-> LoadedApk.java]

private void initializeJavaContextClassLoader() {
    IPackageManager pm = ActivityThread.getPackageManager();
    android.content.pm.PackageInfo pi;
    pi = pm.getPackageInfo(mPackageName, 0, UserHandle.myUserId());

    boolean sharedUserIdSet = (pi.sharedUserId != null);
    boolean processNameNotDefault =
        (pi.applicationInfo != null &&
         !mPackageName.equals(pi.applicationInfo.processName));
    boolean sharable = (sharedUserIdSet || processNameNotDefault);
    ClassLoader contextClassLoader =
        (sharable)
        ? new WarningContextClassLoader()
        : mClassLoader;
    //设置当前线程的Context ClassLoader
    Thread.currentThread().setContextClassLoader(contextClassLoader);
}

 

2.10 newApplication

[-> Instrumentation.java]

public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, 
        IllegalAccessException, ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}

此处 cl 便是前面 getClassLoader() 所获取的 PathClassLoader 对象。通过其方法 loadClass() 来加载目标 Application 对象;

 


2.10.1 newApplication

[-> Instrumentation.java]

static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, 
        IllegalAccessException, ClassNotFoundException {
   Application app = (Application)clazz.newInstance(); //【见小节2.10.2】
   app.attach(context); //【见小节2.10.3】
   return app;
}


2.10.2 Application初始化

[-> Application.java]

public class Application extends ContextWrapper implements ComponentCallbacks2 {
    public LoadedApk mLoadedApk;

    public Application() {
        super(null);
    }
}


2.10.3 App.attach

[-> Application.java]

final void attach(Context context) {
    attachBaseContext(context); //Application的mBase
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

该方法主要功能:
(1) 将新创建的 ContextImpl 对象保存到 Application 的父类成员变量 mBase;
(2) 将新创建的 LoadedApk 对象保存到 Application 的父员变量 mLoadedApk;


三. App进程

3.1 ActivityThread.main

[-> ActivityThread.java]

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

这是运行在app进程,当进程由 zygote fork 后执行 ActivityThread 的 main 方法。


3.2 AT.attach

[-> ActivityThread.java]

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        //初始化RuntimeInit.mApplicationObject值
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        mgr.attachApplication(mAppThread); //[见小节3.3]
    } else {
        ...
    }
}

经过binder调用,进入system_server进程,执行如下操作。


3.3 AMS.attachApplication

[-> ActivityManagerService.java]

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

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    ProcessRecord app;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid); //根据pid获取ProcessRecord
        }
    }
    ...

    ApplicationInfo appInfo = app.instrumentationInfo != null ? app.instrumentationInfo : app.info;
    //[见流程3.4]
    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());
    ...

    return true;
}

system_server 收到 attach 操作, 然后再向新创建的进程执行 handleBindApplication() 过程:


3.4 AT.handleBindApplication

[-> ActivityThread.java ::H]

当主线程收到 H.BIND_APPLICATION,则调用 handleBindApplication

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    Process.setArgV0(data.processName); //设置进程名
    ...
    //获取LoadedApk对象[见小节3.5]
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...

    // 创建ContextImpl上下文[2.6.4]
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ...

    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象[见小节2.7]
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        mInstrumentation.onCreate(data.instrumentationArgs);
        //回调onCreate [见小节3.4.1]
        mInstrumentation.callApplicationOnCreate(app);
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

在 handleBindApplication() 的过程中,会同时设置以下两个值:

(1) LoadedApk.mApplication
(2) ActivityThread.mInitialApplication

 


3.4.1 onCreate

[-> Instrumentation.java]

public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

 

3.5 getPackageInfoNoCheck

[-> ActivityThread.java]

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, 
        boolean securityViolation, boolean includeCode, boolean registerPackage) {
    final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
    synchronized (mResourcesManager) {
        WeakReference<LoadedApk> ref;
        if (differentUser) {
            ref = null;
        } else if (includeCode) {
            ref = mPackages.get(aInfo.packageName); //从mPackages查询
        } else {
            ...
        }

        LoadedApk packageInfo = ref != null ? ref.get() : null;
        if (packageInfo == null || (packageInfo.mResources != null
                && !packageInfo.mResources.getAssets().isUpToDate())) {
            //创建LoadedApk对象
            packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader,
                        securityViolation, includeCode &&
                        (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

            if (mSystemThread && "android".equals(aInfo.packageName)) {
                ...
            }

            if (differentUser) {
                ...
            } else if (includeCode) {
                //将新创建的LoadedApk加入到mPackages
                mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo));
            } else {
                ...
            }
        }
        return packageInfo;
    }
}

创建 LoadedApk 对象,并将新创建的 LoadedApk 加入到 mPackages. 也就是说每个app都会创建唯一的 LoadedApk 对象. 此处 aInfo 来源于 ProcessRecord.info 变量, 也就是进程中的第一个app.


四. 总结

1. system_server进程

其 application 创建过程都创建对象有 ActivityThread,Instrumentation, ContextImpl,LoadedApk,Application。流程图如下:


2. app进程

其 application 创建过程都创建对象有 ActivityThread,ContextImpl,LoadedApk,Application。 流程图如下:

App进程的 Application 创建过程,跟system进程的核心逻辑都差不多。只是app进程多了两次binder调用。

 

 

参考:
理解Application创建过程: http://gityuan.com/2017/04/02/android-application/

 

标签:创建,app,ContextImpl,ActivityThread,LoadedApk,Application,null,过程
From: https://www.cnblogs.com/hellokitty2/p/17629294.html

相关文章

  • C# System.InvalidOperationException:“线程间操作无效: 从不是创建控件“****”的线
     在程序主入口,构造函数加载时,添加如下代码//如果捕获了对错误线程的调用,则为true;否则为falseSystem.Windows.Forms.Control.CheckForIllegalCrossThreadCalls=false;解释:多线程程序中,新创建的线程不能访问UI线程创建的窗口控件,这时如果想要访问窗口的控......
  • Angular如何创建路由以及如何配置路由导航
    废话不多说直接进入正题,首先要创建好项目。第一步:安装Angular路由输入以下指令npminstall@angular/router第二部:通过指令创建Angular路由守卫nggguardguards/auth(自定义名字)第二部:在module文件里面导入①路由导航组件②其他类组件,之后再NgModule({declarations:......
  • mysql账号密码失效后无法修改密码问题处理过程
    --修改密码alterusermeet@'%'identifiedwithmysql_native_passwordby'123456';--修改账户有效期alteruser'meet'@'%'passwordexpireinterval600day;报错处理:ERROR1396(HY000):OperationALTERUSERfailedfor'meet�......
  • 可独立创建应用的SaaS多租户低代码平台之租户的应用管理说明
    在IT系统中,“租户”(tenant)通常用于指代一种多租户架构(multi-tenancy),它是一种软件架构模式,允许多个用户或组织共享相同的应用程序或系统实例,但彼此之间的数据和配置被隔离开来,拥有自己的用户、数据、配置和权限,保证每个租户的数据隐私和安全性。JVS的多租户架构是通过逻辑隔离的方式......
  • 使用Spring initializr快速创建一个springboot项目
     第一步首先new一个新的project选择Springinitializr配置好相关信息后下一步编辑在左上角我们可以选择SprinBoot的版本,在这里直接加入web依赖springweb和Template的Thymeleaf依赖,点上对勾后可以在最右边里看到你选择的依赖,然后点击create编辑可以看到我们的项目结构,很多sprin......
  • 记一次Thinkphp5.0.23复现过程
    环境:Windows11专业版22H2工具:phpStudy2018、thinkphp5.0.23、burp专业版、Firefox浏览器说明:一开始是打算使用linux中的docker上搭建靶场的奈何因为dockerhub是国外的弄了一天没拉取下来包只好去gitee把这个包下载下来使用win平台自己搭建一下了1.安装phpstudy2018和......
  • win10中Docker安装、构建镜像、创建容器、Vscode连接实例
    Docker方便一键构建项目所需的运行环境:首先构建镜像(Image)。然后镜像实例化成为容器(Container),构成项目的运行环境。最后Vscode连接容器,方便我们在本地进行开发。下面以一个简单的例子介绍在win10中实现:Docker安装、构建镜像、创建容器、Vscode连接使用。Docker安装首先进......
  • CH32V003在MRS中的初始化过程
    在MRS的默认配置中,在main函数执行之前,就已经执行了时钟的初始化配置程序,这部分程序被放在了一个名为system_ch32v00x.c的文件中,这个文件默认被加载到MRS的User目录下(可双击打开它)。在该文件中,最重要的一个函数就是SystemInit,它负责系统的初始化工作,其代码如下所示。 voidSyste......
  • PXE操作过程 kickstart 无人值守安装
    PXE操作过程分配给同一局域网内新加机器的地址(配置文件)dhcp分配地址指明tftp服务器的地址tftp服务端开启udp配置默认关闭安装syslinux取得pxelinux.0文件安装vsftpd服务挂载软件安装源(mount/dev/sr0/var/ftp/centos7)将四大文件拷入(/var/lib/tftpboot......
  • org.springframework.context.ApplicationContextException: Failed to start bean 'd
    ##    一、报错信息org.springframework.context.ApplicationContextException:Failedtostartbean'documentationPluginsBootstrapper';nestedexceptionisjava.lang.NullPointerException具体报错信息如下:##  二、报错原因     SpringBoot2......