前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android ANR与OOM

Android ANR与OOM

作者头像
Yif
发布2019-12-26 15:13:41
8390
发布2019-12-26 15:13:41
举报
文章被收录于专栏:Android 进阶

Android 应用程序启动过程

Activity启动过程可以分为两种:一种是根activity的启动过程,另一种是普通activity启动过程。

activity指的是应用程序启动的第一个activity,因此也可以理解为应用程序的启动过程。普通activity除根activity以外的其他activity

  • activity启动涉及4个进程:Zygote进程,Launcher进程、AMS所在的进程(systemServer进程)与应用程序进程
  • 普通activity启动只涉及AMS所在进程与应用程序进程。

根Activity启动流程

  • 点击桌面应用图标,Launcher进程将启动Activity的请求以Binder的方式发送给了AMS
  • AMS接收到启动请求后,判断根activity所需的应用程序进程是否存在并启动,不存在以Socket方式请求Zygote进程fork新进程。同时交付ActivityStarter处理IntentFlag等信息,然后再交给ActivityStackSupervisior/ActivityStack处理Activity进栈相关流程。
  • Zygote接收到新进程创建请求后fork出新进程。
  • 在新进程里创建ActivityThread对象,新创建的进程就是应用的主线程,在主线程里开启Looper消息循环,开始处理创建Activity
  • ActivityThread利用ClassLoader去加载Activity、创建Activity实例,并回调Activity的onCreate()方法。这样便完成了Activity的启动。

为什么zygote使用socket通信不使用binder通信

  1. zygoteservice manager 先启动;从这个意义上,他没有 service manager 可以注册,所以没法用 binder
  2. 因为他们两个都是 init 进程启动的,就算先启动 service manager,也不能保存 zygote 起来的时候 service manger 就已经初始化好了(这就需要额外的同步,太麻烦);
  3. 这个 socket 的所有者是 rootgroupsystem,只有系统权限的用户才能读写,这又多了一个安全保障(注意,这个 socketUnixsocket,不是 internet 域 socket);

AMS 大家族

  • ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期。
  • ActivityThreadApp的真正入口。当开启App之后,调用main()开始运行,开启消息循环队列,这就是传说的UI线程或者叫主线程。与ActivityManagerService一起完成Activity的管理工作。
  • ApplicationThread:用来实现ActivityManagerServieActivityThread之间的交互。在ActivityManagerSevice需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通信。
  • ApplicationThreadProxy:是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通信。AMS就是通过该代理与ActivityThread进行通信的。
  • Instrumentation:监控应用与系统相关的交互行为,每一个应用程序只有一个Instrumetation对象,每个Activity内都有一个对该对象的引用,Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
  • ActivityStack:Activity在AMS的栈管理,用来记录经启动的Activity的先后关系,状态信息等。通过ActivtyStack决定是否需要启动新的进程。
  • ActivityRecordActivityStack的管理对象,每个Acivity在AMS对应一个ActivityRecord,来记录Activity状态以及其他的管理信息。其实就是服务器端的Activit对象的映像。
  • TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个Task包含若干个ActivityRecordAMSTaskRecord确保Activity启动和退出的顺序。
  • ActivityStarter:Activity启动的控制器,处理Intent与Flag对Activity启动的影响,具体说来有:
    • 寻找符合启动条件的Activity,如果有多个,让用户选择;
    • 校验启动参数的合法性;
    • 返回int参数,代表Activity是否启动成功。
  • ActivityStackSupervisior:这个类的作用你从它的名字就可以看出来,它用来管理任务栈。

Activity 启动流程源码分析

Activity 调用startActivity最终都会调用startActivityForResult方法

代码语言:javascript
复制
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
            //判读当前Activity是否为空,为空调用Instrumentation的execStartActivity进行创建
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
           ......
    }

execStartActivity方法

代码语言:javascript
复制
public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

启动Activity最终调用的是ActivityManager.getService().startActivity方法,而ActivityManager.getService()返回的是IActivityManager对象,它是一个Binder对象。 ActivityManagerService继承自IActivityManager.Stub对象。 getService方法如下:

代码语言:javascript
复制
public static IActivityManager getService() {
//获取IActivityManagerSingleton实例
        return IActivityManagerSingleton.get();
    }
//创建IActivityManagerSingleton实例对象
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = 
                    //将服务端对象转换成客户端所需的AIDL接口对象,由于ActivityManagerService继承自IActivityManager.Stub对象。所以这里就返回了ActivityManagerService对象实例
                    IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

所以ActivityManager.getService().startActivity方法实质上调用的是ActivityManagerService的startActivity方法。 checkStartActivityResult方法是用来检查Activity启动的结果,比如没有在AndroidManifest.xml中注册这个Activity实例对象。

代码语言:javascript
复制
public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }
 
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startAssistantActivity does not match active session");
            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start assistant activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

ActivityManagerService的startActivity方法。

代码语言:javascript
复制
 @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
 
    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }

调用了startActivityMayWait方法进入到了ActivityStarter类中,而startActivityMayWait中又调用了startActivityLocked方法

代码语言:javascript
复制
 final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            TaskRecord inTask, String reason) {
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
                    reason);
}

ActivityStarter类中startActivityMayWait—>startActivityLocked->startActivity->startActivityUnchecked然后调用resumeFocusedStackTopActivityLocked方法进入到了ActivityStackSupervisior类中。

代码语言:javascript
复制
boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
 
        if (!readyToResume()) {
            return false;
        }
 
        if (targetStack != null && isFocusedStack(targetStack)) {
        //当期ActivityStack不为空就调用resumeTopActivityUncheckedLocked方法
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
 
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
 
        return false;
    }

当期ActivityStack不为空就调用resumeTopActivityUncheckedLocked方法,在这个方法中又调用了resumeTopActivityInnerLocked方法 mStackSupervisor.startSpecificActivityLocked(next, true, true);

代码语言:javascript
复制
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.getStack().setLaunchTime(r);
 
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
 
        }

内部调用realStartActivityLocked开始真正的启动Activity

代码语言:javascript
复制
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
  ......
  app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);
.....
}

这里的app.thread.就是IApplicationThread,它继承自IInterface,是一个Binder对象,包含大量启动与停止Activity接口,还包含服务。 private class ApplicationThread extends IApplicationThread.Stub ActivityThread内部类ApplicationThread继承IApplicationThread.Stub对象,所以app.thread.scheduleLaunchActivity方法调用实质就是调用ApplicationThreadscheduleLaunchActivity方法。

代码语言:javascript
复制
 @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
 
            updateProcessState(procState, false);
 
            ActivityClientRecord r = new ActivityClientRecord();
 
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;
 
            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;
 
            r.startsNotResumed = notResumed;
            r.isForward = isForward;
 
            r.profilerInfo = profilerInfo;
 
            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);
 
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

scheduleLaunchActivity做的事很简单,就是通过handler发送一个启动Activity的消息。

代码语言:javascript
复制
 case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
 
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

然后调用handleLaunchActivity来处理

代码语言:javascript
复制
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            Activity a = performLaunchActivity(r, customIntent);
            ......
}

内部又调用performLaunchActivity来创建Activity 首先获取Activity的组件信息

代码语言:javascript
复制
 ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
 
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }
 
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

然后通过Instrumentation.newActivity使用ClassLoader类加载器去创建Activity实例对象

代码语言:javascript
复制
try {
            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);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

再通过Application app = r.packageInfo.makeApplication(false, mInstrumentation);创建Application对象实例,方法内部进行判断是否已经创建,创建过后就不会再次创建。 创建ContextImpl对象并通过Activity的attach方法进行一些重要的数据初始化操作,ContextImpl是一种重要的数据结构,是Context的具体实现,Context的大部分逻辑都是通过ContextImpl来完成的。它是通过Activity的attach方法进行与Activity关联的。

代码语言:javascript
复制
 activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

最后调用Activity的onCreate方法完成Activity的创建

代码语言:javascript
复制
activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
 
    }
public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
}

Activity的onCreate方法

代码语言:javascript
复制
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        mActivityTransitionState.readState(icicle);
 
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年9月5日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Android 应用程序启动过程
    • 根Activity启动流程
      • 为什么zygote使用socket通信不使用binder通信
        • AMS 大家族
        • Activity 启动流程源码分析
        相关产品与服务
        云服务器
        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档