【Android12】Android Framework系列--AMS启动Activity分析

AMS启动Activity分析

通过ActivityManagerService(AMS)提供的方法,可以启动指定的Activity。比如Launcher中点击应用图标后,调用AMS的startActivity函数启动应用。
AMS提供的服务通过IActivityManager.aidl文件定义。

// frameworks/base/core/java/android/app/IActivityManager.aidl
package android.app;
// 省略
/*** System private API for talking with the activity manager service.  This* provides calls from the application back to the activity manager.** {@hide}*/
interface IActivityManager {// 省略/** @deprecated Use {@link #startActivityWithFeature} instead */@UnsupportedAppUsage(maxTargetSdk=29, publicAlternatives="Use {@link android.content.Context#startActivity(android.content.Intent)} instead")int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,int flags, in ProfilerInfo profilerInfo, in Bundle options);int startActivityWithFeature(in IApplicationThread caller, in String callingPackage,in String callingFeatureId, in Intent intent, in String resolvedType,in IBinder resultTo, in String resultWho, int requestCode, int flags,in ProfilerInfo profilerInfo, in Bundle options);// 省略
}

代码版本是Android12。分析一下从应用侧(比如Launcher)调用startActivity启动另一个应用的流程。
在这里插入图片描述

startActivity源码分析

应用侧可以通过context的startActivity函数调用AMS。比如下述例子。

Intent intent = new Intent();
// 启动com.linduo.test这个Package中的  MainActivity
intent.setComponent(new ComponentName("com.linduo.test", "com.linduo.test.MainActivity"));
context.startActivity(intent);

context是abstract的类,其实现在ContextImpl中。

// frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
}// frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
@Override
public void startActivity(Intent intent) {warnIfCallingFromSystemProcess();startActivity(intent, null);
}@Override
public void startActivity(Intent intent, Bundle options) {warnIfCallingFromSystemProcess();// Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is// generally not allowed, except if the caller specifies the task id the activity should// be launched in. A bug was existed between N and O-MR1 which allowed this to work. We// maintain this for backwards compatibility.final int targetSdkVersion = getApplicationInfo().targetSdkVersion;if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0&& (targetSdkVersion < Build.VERSION_CODES.N|| targetSdkVersion >= Build.VERSION_CODES.P)&& (options == null|| ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity "+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."+ " Is this really what you want?");}mMainThread.getInstrumentation().execStartActivity(getOuterContext(), mMainThread.getApplicationThread(), null,(Activity) null, intent, -1, options);
}
}

ContextImpl通过mMainThread(ActivityThread类型)得到了Instrumentation对象,调用Instrumentation的execStartActivity函数。execStartActivity函数中,如果开启了Activity监听模式,会通知监听者onStartActivity,然后调用ActivityTaskManagerService的startActivity函数启动Activity。最后检查启动的结果,如果启动失败抛出对应的异常。
onStartActivity的监听,可以使用Instrumentation.addMonitor方式,具体内容可以查看Instrumentation.java

// frameworks/base/core/java/android/app/Instrumentation.java
@UnsupportedAppUsage
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) {// 如果开启了监听,会给监听者通过 onStartActivitysynchronized (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(who);intent.prepareToLeaveProcess(who);// 调用ActivityTaskManagerService( AMS中提供的服务)int result = ActivityTaskManager.getService().startActivity(whoThread,who.getOpPackageName(), who.getAttributionTag(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()), token,target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);// 检查启动的结果,如果失败会throw异常。checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;
}

ActivityTaskManagerService继承了IActivityTaskManager.Stub,属于AMS提供的服务。在其startActivity函数中,会调用startActivityAsUser,判断package与UID是否相符、是否为Isolated模式的应用、并检查用户权限(源码中可以看出系统用户权限非常大,所以为了安全要慎用系统用户权限),最终调用ActivityStarterexecute启动Activity。

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions) {// 调用startActivityAsUserreturn startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());
}@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,Bundle bOptions, int userId) {// 调用startActivityAsUser,validateIncomingUser为truereturn startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,true /*validateIncomingUser*/);
}private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {// 判断调用的package和UID相符assertPackageMatchesCallingUid(callingPackage);// 禁止来自Isolated模式应用的调用enforceNotIsolatedCaller("startActivityAsUser");// 检测用户权限。这个函数中,可以看出系统用户权限非常大(感兴趣的可以看一下)userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// 通过ActivityStartController,取得ActivityStarter,设置好系列参数后调用execute// TODO: Switch to user app stacks here.return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId).execute();}

ActivityStarter的execute函数中,再次进行了一些检查,比如是否存在文件句柄泄露(Intent)、config是否要变更,并调用了executeRequest函数。

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {try {// Refuse possible leaked file descriptorsif (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");}final LaunchingState launchingState;synchronized (mService.mGlobalLock) {final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID?  Binder.getCallingUid() : mRequest.realCallingUid;launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mRequest.intent, caller, callingUid);}// If the caller hasn't already resolved the activity, we're willing// to do so here. If the caller is already holding the WM lock here,// and we need to check dynamic Uri permissions, then we're forced// to assume those permissions are denied to avoid deadlocking.if (mRequest.activityInfo == null) {mRequest.resolveActivity(mSupervisor);}// Add checkpoint for this shutdown or reboot attempt, so we can record the original// intent action and package name.if (mRequest.intent != null) {String intentAction = mRequest.intent.getAction();String callingPackage = mRequest.callingPackage;if (intentAction != null && callingPackage != null&& (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)|| Intent.ACTION_SHUTDOWN.equals(intentAction)|| Intent.ACTION_REBOOT.equals(intentAction))) {ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);}}int res;synchronized (mService.mGlobalLock) {final boolean globalConfigWillChange = mRequest.globalConfig != null&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;// 获取当前处于Top且Focus的RootTaskfinal Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();if (rootTask != null) {// RookTask非空,更新一下ConfigChange的Flag。rootTask.mConfigWillChange = globalConfigWillChange;}ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "+ "will change = %b", globalConfigWillChange);final long origId = Binder.clearCallingIdentity();res = resolveToHeavyWeightSwitcherIfNeeded();if (res != START_SUCCESS) {return res;}// 这个函数中,会创建ActivityRecord,并启动Activityres = executeRequest(mRequest);// 后面的函数,主要是Config的变更。如果有变化会给config变化的通知。// 以及结果的检查。Binder.restoreCallingIdentity(origId);if (globalConfigWillChange) {// If the caller also wants to switch to a new configuration, do so now.// This allows a clean switch, as we are waiting for the current activity// to pause (so we will not destroy it), and have not yet started the// next activity.mService.mAmInternal.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,"updateConfiguration()");if (rootTask != null) {rootTask.mConfigWillChange = false;}ProtoLog.v(WM_DEBUG_CONFIGURATION,"Updating to new configuration after starting activity.");mService.updateConfigurationLocked(mRequest.globalConfig, null, false);}// The original options may have additional info about metrics. The mOptions is not// used here because it may be cleared in setTargetRootTaskIfNeeded.final ActivityOptions originalOptions = mRequest.activityOptions != null? mRequest.activityOptions.getOriginalOptions() : null;// If the new record is the one that started, a new activity has created.final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;// Notify ActivityMetricsLogger that the activity has launched.// ActivityMetricsLogger will then wait for the windows to be drawn and populate// WaitResult.mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,newActivityCreated, mLastStartActivityRecord, originalOptions);if (mRequest.waitResult != null) {mRequest.waitResult.result = res;res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,launchingState);}return getExternalResult(res);}} finally {onExecutionComplete();}
}

ActivityStarter的executeRequest比较长,下面省略一部分内容。根据其注释内容“Executing activity start request and starts the journey of starting an activity”也可以看出,在这里处理了activity启动的请求。函数中,进行了权限检查,包括判断了是否为Home应用,创建了ActivityRecord记录这次启动为最后一次启动的Activity,然后调用startActivityUnchecked启动应用。

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Executing activity start request and starts the journey of starting an activity. Here* begins with performing several preliminary checks. The normally activity launch flow will* go through {@link #startActivityUnchecked} to {@link #startActivityInner}.*/
private int executeRequest(Request request) {// 检查启动 权限boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,requestCode, callingPid, callingUid, callingPackage, callingFeatureId,request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,resultRootTask);abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,callingPid, resolvedType, aInfo.applicationInfo);abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,callingPackage);boolean restrictedBgActivity = false;if (!abort) {try {Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,"shouldAbortBackgroundActivityStart");// 判断是否可以启动Activity.// 这里也会判断是否为Home应用,如果是Home应用的可以启动。如果不是,还要进行其他判断。restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,request.originatingPendingIntent, request.allowBackgroundActivityStart,intent);} finally {Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);}}// 创建ActivityRecordfinal ActivityRecord r = new ActivityRecord.Builder(mService).setCaller(callerApp).setLaunchedFromPid(callingPid).setLaunchedFromUid(callingUid).setLaunchedFromPackage(callingPackage).setLaunchedFromFeature(callingFeatureId).setIntent(intent).setResolvedType(resolvedType).setActivityInfo(aInfo).setConfiguration(mService.getGlobalConfiguration()).setResultTo(resultRecord).setResultWho(resultWho).setRequestCode(requestCode).setComponentSpecified(request.componentSpecified).setRootVoiceInteraction(voiceSession != null).setActivityOptions(checkedOptions).setSourceRecord(sourceRecord).build();// 记录为最后一次启动的ActivitymLastStartActivityRecord = r;// 调用startActivityUnchecked,启动ActivitymLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,restrictedBgActivity, intentGrants);if (request.outActivity != null) {request.outActivity[0] = mLastStartActivityRecord;}return mLastStartActivityResult;
}

ActivityStarter的startActivityUnchecked函数会调用startActivityInner函数,在这个函数中获取加载Activity的RootTask加载Activity,并调用RootWindowContainer的resumeFocusedTasksTopActivities函数fork出一个进程来运行Activity。


// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java/*** Start an activity while most of preliminary checks has been done and caller has been* confirmed that holds necessary permissions to do so.* Here also ensures that the starting activity is removed if the start wasn't successful.*/
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,boolean restrictedBgActivity, NeededUriGrants intentGrants) {// 省略try {mService.deferWindowLayout();Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");// 调用startActivityInnerresult = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);} finally {// 省略}postStartActivityProcessing(r, result, startedActivityRootTask);return result;
}/*** Start an activity and determine if the activity should be adding to the top of an existing* task or delivered new intent to an existing activity. Also manipulating the activity task* onto requested or valid root-task/display.** Note: This method should only be called from {@link #startActivityUnchecked}.*/// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
@VisibleForTesting
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,boolean restrictedBgActivity, NeededUriGrants intentGrants) {// 省略if (mTargetRootTask == null) {// 获取目标RootTaskmTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);}// 调用RootTask,startActivity(细节可以顺着这个函数看)mTargetRootTask.startActivityLocked(mStartActivity,topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord);// mDoResume为Tureif (mDoResume) {if (!mTargetRootTask.isTopActivityFocusable()|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()&& mStartActivity != topTaskActivity)) {// 省略} else {// If the target root-task was not previously focusable (previous top running// activity on that root-task was not visible) then any prior calls to move the// root-task to the will not update the focused root-task.  If starting the new// activity now allows the task root-task to be focusable, then ensure that we// now update the focused root-task accordingly.if (mTargetRootTask.isTopActivityFocusable()&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {mTargetRootTask.moveToFront("startActivityInner");}mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}}mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);// Update the recent tasks list immediately when the activity startsmSupervisor.mRecentTasks.add(mStartActivity.getTask());mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);return START_SUCCESS;
}

启动的Activity如果是另一个应用,Android会fork出一个进程来加载Activity。那么是在哪里进行的fork?
在ActivityStarter的handleStartResult中,会进行fork进程操作(调用Process.start实现)

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/*** Start an activity while most of preliminary checks has been done and caller has been* confirmed that holds necessary permissions to do so.* Here also ensures that the starting activity is removed if the start wasn't successful.*/
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, boolean restrictedBgActivity,NeededUriGrants intentGrants) {int result = START_CANCELED;final Task startedActivityRootTask;// Create a transition now to record the original intent of actions taken within// startActivityInner. Otherwise, logic in startActivityInner could start a different// transition based on a sub-action.// Only do the create here (and defer requestStart) since startActivityInner might abort.final TransitionController transitionController = r.mTransitionController;Transition newTransition = (!transitionController.isCollecting()&& transitionController.getTransitionPlayer() != null)? transitionController.createTransition(TRANSIT_OPEN) : null;RemoteTransition remoteTransition = r.takeRemoteTransition();if (newTransition != null && remoteTransition != null) {newTransition.setRemoteTransition(remoteTransition);}transitionController.collect(r);try {mService.deferWindowLayout();Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,intentGrants);} finally {Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);// 这里会fork出一个进程(调用RootWindowContainer.ensureVisibilityAndConfig),最终调用Process.startstartedActivityRootTask = handleStartResult(r, options, result, newTransition,remoteTransition);mService.continueWindowLayout();}postStartActivityProcessing(r, result, startedActivityRootTask);return result;
}

下面是调用的堆栈(Android13输出的,大概流程一样),感兴趣的可以依照堆栈看源码.

ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startProcessAsync(ActivityTaskManagerService.java:4683)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskSupervisor.startSpecificActivity(ActivityTaskSupervisor.java:1013)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.makeVisibleAndRestartIfNeeded(EnsureActivitiesVisibleHelper.java:265)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState(EnsureActivitiesVisibleHelper.java:191)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.process(EnsureActivitiesVisibleHelper.java:139)
ActivityTaskManager:     at com.android.server.wm.TaskFragment.updateActivityVisibilities(TaskFragment.java:985)
ActivityTaskManager:     at com.android.server.wm.Task.lambda$ensureActivitiesVisible$15(Task.java:4866)
ActivityTaskManager:     at com.android.server.wm.Task$$ExternalSyntheticLambda20.accept(Unknown Source:10)
ActivityTaskManager:     at com.android.server.wm.Task.forAllLeafTasks(Task.java:3185)
ActivityTaskManager:     at com.android.server.wm.Task.ensureActivitiesVisible(Task.java:4865)
ActivityTaskManager:     at com.android.server.wm.DisplayContent.lambda$ensureActivitiesVisible$46(DisplayContent.java:6000)
ActivityTaskManager:     at com.android.server.wm.DisplayContent$$ExternalSyntheticLambda17.accept(Unknown Source:10)
ActivityTaskManager:     at com.android.server.wm.Task.forAllRootTasks(Task.java:3197)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1799)
ActivityTaskManager:     at com.android.server.wm.DisplayContent.ensureActivitiesVisible(DisplayContent.java:5999)
ActivityTaskManager:     at com.android.server.wm.RootWindowContainer.ensureActivitiesVisible(RootWindowContainer.java:2075)
ActivityTaskManager:     at com.android.server.wm.RootWindowContainer.ensureVisibilityAndConfig(RootWindowContainer.java:1876)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.handleStartResult(ActivityStarter.java:1669)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1598)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1185)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:672)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1243)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1215)
ActivityTaskManager:     at android.app.IActivityTaskManager$Stub.onTransact(IActivityTaskManager.java:969)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.onTransact(ActivityTaskManagerService.java:5152)
ActivityTaskManager:     at android.os.Binder.execTransactInternal(Binder.java:1179)
ActivityTaskManager:     at android.os.Binder.execTransact(Binder.java:1143)
ActivityTaskManager: java.lang.Throwable

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/263914.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql数据库文件丢失恢复---惜分飞

客户服务器重启,mysql相关数据文件丢失 通过底层工具进行分析,无法正确恢复数据库名字,一个个单个ibd文件(而且很多本身是错误的) 对于这种情况,通过mysql block扫描恢复出来page文件 恢复出来客户需要数据 这个客户出现该故障的原因大概率是由于文件系统损坏导致.最终…

[ 蓝桥杯Web真题 ]-布局切换

目录 介绍 准备 目标 规定 思路 解法参考 介绍 经常用手机购物的同学或许见过这种功能&#xff0c;在浏览商品列表的时候&#xff0c;我们通过点击一个小小的按钮图标&#xff0c;就能快速将数据列表在大图&#xff08;通常是两列&#xff09;和列表两种布局间来回切换。…

四. 基于环视Camera的BEV感知算法-BEVFormer

目标 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比5. BEVFormerv2总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章—…

【数据结构实践课设】新生报道注册管理信息系统

目录 1.主要框架 2.写入文件 3.读取文件 4.注册学生信息 5.增加学生信息 6.删除学生信息 7.按姓名查询 8.按班级查询 9.按专业查询 10.打印学生信息 11.完整代码 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所…

关于图像清晰度、通透度的描述

1、问题背景 在图像评测过程中&#xff0c;从主观上一般怎么去评判一副图像的优劣呢&#xff1f; 比较显而易见的就是图像的清晰度和通透度&#xff0c;他们决定了评判者对画质的第一印象。 那怎么去理解图像的清晰度和通透度呢&#xff1f;这是本文要描述的内容。 2、问题分…

单调栈结构

单调栈 单调栈是一种特殊设计的栈结构&#xff0c;为了解决如下的问题&#xff1a; 给定一个可能含有重复数值的 arr[]&#xff0c;i位置的数一定存在如下两种信息&#xff1a; arr[i]的左侧离 i 最近并且小于&#xff08;或者大于&#xff09;arr[i] 的数在哪&#xff1f;arr…

《深入理解计算机系统》学习笔记 - 第四课 - 浮点数

Floating Point 浮点数 文章目录 Floating Point 浮点数分数二进制示例能代表的数浮点数的表示方式浮点数编码规格化值规格化值编码示例 非规格化的值特殊值 示例IEEE 编码的一些特殊属性四舍五入&#xff0c;相加&#xff0c;相乘四舍五入四舍五入的模式二进制数的四舍五入 浮…

MATLAB | 官方举办的动图绘制大赛 | 第四周(收官周)赛情回顾

MATHWORKS官方举办的迷你黑客大赛第三期(MATLAB Flipbook Mini Hack)圆满结束&#xff0c;虽然我的水平和很多大佬还有比较大的差距&#xff0c;但所有奖也算是拿满了&#xff1a; 专家评选前三名&#xff0c;以及投票榜前十&#xff1a;~ 每周的阶段性获奖者&#xff1a; 下面…

16ASM 分段和机器码

8086CPU存储分段管理 问题1&#xff1a;8086是16位cpu&#xff0c;最多可访问&#xff08;寻址&#xff09;多大内存&#xff1f; 运算器一次最多处理16位的数据。地址寄存器的最大宽度为16位。访问的最大内存为&#xff1a;216 64K 即 0000 - FFFF。 问题2&#xff1a;808…

解决方案:aarch64 ARM架构下安装Miniconda + 离线迁移Conda环境的全流程 踩坑避坑指南

目录 一、安装Miniconda1.1、确认本机架构1.2、下载Miniconda安装包1.3、安装Miniconda 二、离线配置Conda环境2.1、查看本机配置2.2、迁移虚拟环境2.3、可能遇见的报错 最后 在ARM架构下&#xff0c;由于Anaconda并不提供官方的ARM版本&#xff0c;在很多情况下强行在ARM系统中…

【图片版】计算机组成原理考前复习题【第2章 运算方法和运算器-2】

目录 前言 考前复习题&#xff08;必记&#xff09;​编辑 结尾 前言 在计算机组成原理的学习过程中&#xff0c;我们深入探索了计算机系统概述这一重要领域。计算机系统作为现代科技的核心&#xff0c;是整个计算机科学的基石。我们将学到的知识与理论转化为了能够解决现实…

为什么需要 Kubernetes,它能做什么?

传统部署时代&#xff1a; 早期&#xff0c;各个组织是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用&#xff0c;因此会导致资源分配问题。 例如&#xff0c;如果在同一台物理服务器上运行多个应用程序&#xff0c; 则可能会出现一个应用程…