Android Java crash原理

Android系統(tǒng)發(fā)生Java crash時(shí)候酌壕,沒有去捕獲處理它的話蒸播,它就會(huì)一路往上拋,最終來到main函數(shù)场航,如果main函數(shù)也沒有處理這個(gè)異常缠导,就會(huì)給到JVM來處理,JVM會(huì)給到當(dāng)前的線程Thread來處理溉痢。

art/runtime/well_known_classes.cc

java_lang_Thread_dispatchUncaughtException = CacheMethod(env, java_lang_Thread, false, "dispatchUncaughtException", "(Ljava/lang/Throwable;)V");

調(diào)用到當(dāng)前線程的dispatchUncaughtException 方法

libcore/ojluni/src/main/java/java/lang/Thread.java
      /**
       * Dispatch an uncaught exception to the handler. This method is
       * intended to be called only by the runtime and by tests.
       *這個(gè)方法只能被runtime執(zhí)行僻造, 當(dāng)現(xiàn)成出現(xiàn)沒有捕獲的異常的時(shí)候執(zhí)行憋他,
       * @hide
       */
     public final void dispatchUncaughtException(Throwable e) {
         Thread.UncaughtExceptionHandler initialUeh =
                 Thread.getUncaughtExceptionPreHandler();
         if (initialUeh != null) {
             try {
                 initialUeh.uncaughtException(this, e);
             } catch (RuntimeException | Error ignored) {
                 // Throwables thrown by the initial handler are ignored
             }
         }
         getUncaughtExceptionHandler().uncaughtException(this, e);
     }

    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

如果沒有設(shè)置uncaughtExceptionHandler,將使用線程所在的線程組(ThreadGroup)來處理這個(gè)未捕獲異常髓削。線程組ThreadGroup實(shí)現(xiàn)了UncaughtExceptionHandler竹挡,所以可以用來處理未捕獲異常。

libcore/ojluni/src/main/java/java/lang/ThreadGroup.java
    public void uncaughtException(Thread t, Throwable e) {
        if (parent != null) {
            parent.uncaughtException(t, e);
        } else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

默認(rèn)情況下立膛,ThreadGroup處理未捕獲異常的邏輯是:
1揪罕、首先將異常消息通知給父線程組(如果parent不為空的話);
2宝泵、然后嘗試?yán)靡粋€(gè)默認(rèn)的defaultUncaughtExceptionHandler來處理異常好啰;
3、如果沒有默認(rèn)的異常處理器則將錯(cuò)誤信息輸出打印到System.err儿奶。

如果設(shè)置了uncaughtExceptionHandler 坎怪,誰回調(diào)下面的這個(gè)接口就可以處理crash異常。

/libcore/ojluni/src/main/java/java/lang/Thread.java
      @FunctionalInterface
      public interface UncaughtExceptionHandler {
          void uncaughtException(Thread t, Throwable e);
      }

setUncaughtExceptionPreHandler

      public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
          return defaultUncaughtExceptionHandler;
      }

      private static volatile UncaughtExceptionHandler uncaughtExceptionPreHandler;
  

      public static void setUncaughtExceptionPreHandler(UncaughtExceptionHandler eh) {
          uncaughtExceptionPreHandler = eh;
      }

再看下 setUncaughtExceptionPreHandler 是什么時(shí)候設(shè)置的
它的設(shè)置在RuntimeInit.java中
不管是系統(tǒng)進(jìn)程還是App進(jìn)程廓握,啟動(dòng)的時(shí)候都會(huì)走到這里搅窿,進(jìn)行注冊(cè)。

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

      public static final void main(String[] argv) {
          ......
          commonInit();
          ......
      }

      protected static final void commonInit() {
          
          LoggingHandler loggingHandler = new LoggingHandler();
          Thread.setUncaughtExceptionPreHandler(loggingHandler);
          //這里設(shè)置了默認(rèn)的異常處理:KillApplicationHandler隙券。
          Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
      }

再看下KillApplicationHandler:

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

         @Override  //回調(diào)了uncaughtException接口男应,處理異常
          public void uncaughtException(Thread t, Throwable e) {
              try {
......
//上報(bào)給AMS 崩潰異常信息
                  ActivityManager.getService().handleApplicationCrash(
                          mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
              } catch (Throwable t2) {
                  if (t2 instanceof DeadObjectException) {
                      // System process is dead; ignore
                  } else {
                      try {
                          Clog_e(TAG, "Error reporting crash", t2);
                      } catch (Throwable t3) {
                          // Even Clog_e() fails!  Oh well.
                      }
                  }
              } finally {
                  //殺掉進(jìn)程
                  Process.killProcess(Process.myPid());
                  //退出當(dāng)前進(jìn)程
                  System.exit(10);
              }
          }

默認(rèn)的異常處理(殺進(jìn)程)是在RuntimeInit進(jìn)程(作用:app運(yùn)行時(shí)環(huán)境初始化,用來初始化運(yùn)行時(shí)的一系列信息娱仔,其中包含異常處理)的main()方法里設(shè)置的沐飘。

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
      public void handleApplicationCrash(IBinder app,
              ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
          ProcessRecord r = findAppProcess(app, "Crash");
          final String processName = app == null ? "system_server"
                  : (r == null ? "unknown" : r.processName);
  
          handleApplicationCrashInner("crash", r, processName, crashInfo);
      }

參數(shù)eventType是指事件類型,具體如下:
Java層未捕捉的異常:crash
ANR:anr
native層的異常:native_crash
現(xiàn)在我們看的是java的異常牲迫,所以這個(gè)類型傳的是crash耐朴。
接著看handleApplicationCrashInner()函數(shù):

      void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName,
              ApplicationErrorReport.CrashInfo crashInfo) {
          EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
                  UserHandle.getUserId(Binder.getCallingUid()), processName,
                  r == null ? -1 : r.info.flags,
                  crashInfo.exceptionClassName,
                  crashInfo.exceptionMessage,
                  crashInfo.throwFileName,
                  crashInfo.throwLineNumber);
  
          StatsLog.write(StatsLog.APP_CRASH_OCCURRED,
                  Binder.getCallingUid(),
                  eventType,
                  processName,
                  Binder.getCallingPid(),
                  (r != null && r.info != null) ? r.info.packageName : "",
                  (r != null && r.info != null) ? (r.info.isInstantApp()
                          ? StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__TRUE
                          : StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__FALSE)
                          : StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__UNAVAILABLE,
                  r != null ? (r.isInterestingToUserLocked()
                          ? StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__FOREGROUND
                          : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__BACKGROUND)
                          : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN
          );
  
          addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo);
  
          mAppErrors.crashApplication(r, crashInfo);
      }

進(jìn)行系統(tǒng)日志輸出,具體的處理是在addErrorToDropBox()函數(shù)中盹憎。當(dāng)啟動(dòng)Activity時(shí)候筛峭,如果找不到,會(huì)報(bào)錯(cuò)陪每,這個(gè)時(shí)候systemserver進(jìn)程中的啟動(dòng)數(shù)據(jù)依然存在影晓,存在緩存信息,要清除檩禾。

接著看下AppErrors.crashApplication

/frameworks/base/services/core/java/com/android/server/am/AppErrors.java
void crashApplication{
......
crashApplicationInner(......);
......
}

 void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,
            int callingPid, int callingUid) {
......
        synchronized (mService) {
......
            if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
                return;
            }
            
            AppErrorDialog.Data data = new AppErrorDialog.Data();
            data.result = result;
            data.proc = r;

            final Message msg = Message.obtain();
            msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;

            taskId = data.taskId;
            msg.obj = data;
            // 發(fā)送消息挂签,彈出crash對(duì)話框,等待用戶選擇
           //如果選擇重新啟動(dòng)盼产,則從最近任務(wù)列表中找到崩潰進(jìn)程饵婆,再次拉起
           //如果選擇強(qiáng)制退出,則殺掉app戏售,進(jìn)入kill流程
           //如果選擇顯示應(yīng)用信息侨核,則啟動(dòng)系統(tǒng)頁面的intent草穆,打開應(yīng)用詳情頁面
            mService.mUiHandler.sendMessage(msg);
        }
        // 得到用戶選擇結(jié)果
        int res = result.get();

        Intent appErrorIntent = null;
        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
        // 如果是超時(shí)或者取消,則當(dāng)成是強(qiáng)制退出
        if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) {
            res = AppErrorDialog.FORCE_QUIT;
        }
        synchronized (mService) {
            if (res == AppErrorDialog.MUTE) {
                stopReportingCrashesLocked(r);
            }
            // 如果是重新啟動(dòng)
            if (res == AppErrorDialog.RESTART) {
                mService.mProcessList.removeProcessLocked(r, false, true, "crash");
                if (taskId != INVALID_TASK_ID) {
                    try {
                     //1. 從最近的任務(wù)列表中找到崩潰進(jìn)程芹关,再次啟動(dòng)
                        mService.startActivityFromRecents(taskId,
                                ActivityOptions.makeBasic().toBundle());
                    } catch (IllegalArgumentException e) {
                        // Hmm...that didn't work. Task should either be in recents or associated
                        // with a stack.
                        Slog.e(TAG, "Could not restart taskId=" + taskId, e);
                    }
                }
            }
             // 如果是退出
            if (res == AppErrorDialog.FORCE_QUIT) {
                long orig = Binder.clearCallingIdentity();
                try {
                    // Kill it with fire!
                    // 殺掉這個(gè)進(jìn)程
                    mService.mAtmInternal.onHandleAppCrash(r.getWindowProcessController());
                    if (!r.isPersistent()) {
                        mService.mProcessList.removeProcessLocked(r, false, false, "crash");
                        mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
                    }
                } finally {
                    Binder.restoreCallingIdentity(orig);
                }
            }
             // 如果是顯示應(yīng)用信息
            if (res == AppErrorDialog.APP_INFO) {
                appErrorIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                appErrorIntent.setData(Uri.parse("package:" + r.info.packageName));
                appErrorIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
                appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
            }
            if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
                // XXX Can't keep track of crash time for isolated processes,
                // since they don't have a persistent identity.
                mProcessCrashTimes.put(r.info.processName, r.uid,
                        SystemClock.uptimeMillis());
            }
        }

        if (appErrorIntent != null) {
            try {
            // 2. 啟動(dòng)一個(gè)系統(tǒng)頁面的intent 來顯示應(yīng)用信息
                mContext.startActivityAsUser(appErrorIntent, new UserHandle(r.userId));
            } catch (ActivityNotFoundException e) {
                Slog.w(TAG, "bug report receiver dissappeared", e);
            }
        }
    }

makeAppCrashingLocked

private boolean makeAppCrashingLocked(ProcessRecord app,
         String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
     app.setCrashing(true);
     // 封裝崩潰信息到 ProcessErrorStateInfo 中
     app.crashingReport = generateProcessError(app,
             ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
     // 獲取當(dāng)前user的 error receiver续挟;停止廣播接收
     app.startAppProblemLocked();
     // 停是凍結(jié)屏幕
     app.getWindowProcessController().stopFreezingActivities();
     // 調(diào)用 handleAppCrashLocked
     return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
             data);
 }

封裝崩潰信息到 ProcessErrorStateInfo 中
獲取當(dāng)前user的 error receiver紧卒;停止廣播接收
停是凍結(jié)屏幕
handleAppCrashLocked()

boolean handleAppCrashLocked(ProcessRecord app, String reason,
         String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
......
      // 同一個(gè)進(jìn)程侥衬,如果連續(xù)兩次崩潰的間隔小于 一分鐘,則認(rèn)為崩潰過于頻繁
     if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
         // The process crashed again very quickly. If it was a bound foreground service, let's
         // try to restart again in a while, otherwise the process loses!
         Slog.w(TAG, "Process " + app.info.processName
                 + " has crashed too many times: killing!");
         EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
                 app.userId, app.info.processName, app.uid);
                 // 2.8.1 回調(diào) atm的onHandleAppCrash 
         mService.mAtmInternal.onHandleAppCrash(app.getWindowProcessController());
       
         if (!app.isPersistent()) {
           // 如果不是persistent進(jìn)程,則不再重啟跑芳,除非用戶主動(dòng)觸發(fā)
             // We don't want to start this process again until the user
             // explicitly does so...  but for persistent process, we really
             // need to keep it running.  If a persistent process is actually
             // repeatedly crashing, then badness for everyone.
            
             if (!app.isolated) {
                 // XXX We don't have a way to mark isolated processes
                 // as bad, since they don't have a peristent identity.
                 mBadProcesses.put(app.info.processName, app.uid,
                         new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
                 mProcessCrashTimes.remove(app.info.processName, app.uid);
             }
             app.bad = true;
             app.removed = true;
             // Don't let services in this process be restarted and potentially
             // annoy the user repeatedly.  Unless it is persistent, since those
             // processes run critical code.
             // 移除進(jìn)程中的所有服務(wù)
             mService.mProcessList.removeProcessLocked(app, false, tryAgain, "crash");
             // 恢復(fù)頂部的activity
             mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
             if (!showBackground) {
                 return false;
             }
         }
         mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
     } else {
     // 不是一分鐘內(nèi)連續(xù)崩潰
         final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
                         app.getWindowProcessController(), reason);
         if (data != null) {
             data.taskId = affectedTaskId;
         }
         if (data != null && crashTimePersistent != null
                 && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
             data.repeating = true;
         }
     }

......
      // 如果 app的crashHandler存在轴总,則交給其處理
     if (app.crashHandler != null) mService.mHandler.post(app.crashHandler);
     return true;
 }

如果是兩次連續(xù)崩潰小于一分鐘,則認(rèn)為是頻繁崩潰博个。
調(diào)用onHandleAppCrash方法
如果不是persistent進(jìn)程,則不再重啟怀樟,除非用戶主動(dòng)觸發(fā)
移除進(jìn)程中的所有服務(wù),且不再重啟
恢復(fù)棧頂?shù)腶ctivity

不是連續(xù)崩潰盆佣,則記錄崩潰受影響的taskid
如果 app的crashHandler存在往堡,則交給其處理

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Override
public void onHandleAppCrash(WindowProcessController wpc) {
   synchronized (mGlobalLock) {
       mRootActivityContainer.handleAppCrash(wpc);
   }
}

//RootActivityContainer.java
void handleAppCrash(WindowProcessController app) {
   // 遍歷所有的ActivityDisplay
  for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
      final ActivityDisplay display = mActivityDisplays.get(displayNdx);
      // 遍歷ActivityDisplay中管理的所有 ActivityStack 
      for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
         // 獲取activity stack對(duì)象 
          final ActivityStack stack = display.getChildAt(stackNdx);
          stack.handleAppCrash(app);
      }
  }
}

>ActivityStack.java
void handleAppCrash(WindowProcessController app) {
  // 循環(huán)ActivityStack中管理的 TaskRecord
  for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
      // 得到 TaskRecord中管理的所有  ActivityRecord集合
      final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
      // 遍歷 ActivityRecord集合,得到每一個(gè) ActivityRecord對(duì)象
      for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
          final ActivityRecord r = activities.get(activityNdx);
          // 如果是崩潰的進(jìn)程共耍,則銷毀activity
          if (r.app == app) {
                      
              // Force the destroy to skip right to removal.
              r.app = null;
              // 
              getDisplay().mDisplayContent.prepareAppTransition(
                      TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
              // finish銷毀當(dāng)前activity
              finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
                      "handleAppCrashedLocked");
          }
      }
  }
}

AMS端在收到App的崩潰后虑灰,大概流程如下:

把崩潰信息通過 DBS 服務(wù),寫入到Dropbox文件中痹兜。dropbox支持錯(cuò)誤類型:crash穆咐、wtf、anr
停止崩潰進(jìn)程接收廣播字旭;增加ServiceRecord中的crashcount數(shù)对湃;銷毀所有的activies;
彈出崩潰對(duì)話框遗淳,等待用戶選擇

  1. 如果選擇重新啟動(dòng)拍柒,則從最近任務(wù)列表中找到崩潰進(jìn)程,再次拉起
  2. 如果選擇強(qiáng)制退出屈暗,則殺掉app斤儿,進(jìn)入kill流程
  3. 如果選擇顯示應(yīng)用信息,則啟動(dòng)系統(tǒng)頁面的intent恐锦,打開應(yīng)用詳情頁面

Binder服務(wù)死亡通知

在RuntimeInit uncaughtException 末尾會(huì)執(zhí)行
finally {
   // Try everything to make sure this process goes away.
   // 最終關(guān)閉kill掉進(jìn)程
   Process.killProcess(Process.myPid());
   System.exit(10);
}
public static final void killProcess(int pid) {
     sendSignal(pid, SIGNAL_KILL);
 }
public static final native void sendSignal(int pid, int signal);

給指定的進(jìn)程發(fā)送一個(gè) SIGNAL_KILL 信號(hào)往果。應(yīng)用進(jìn)程已經(jīng)被殺死,但是還沒完一铅。因?yàn)閟ystem server進(jìn)程中有注冊(cè)Binder服務(wù)的死亡監(jiān)聽陕贮。當(dāng)App進(jìn)程死亡后,會(huì)回調(diào)到AMS
的死亡監(jiān)聽中潘飘,此時(shí)還需要處理Binder死亡通知回調(diào)邏輯肮之。

在創(chuàng)建進(jìn)程的過程中掉缺,ActivityThread會(huì)調(diào)用AMS的 attachApplication(), 內(nèi)部會(huì)調(diào)用到 attachApplicationLocked()方法。在這里注冊(cè)的Binder的死亡通知戈擒。

ActivityThread.java
@GuardedBy("this")
 private final boolean attachApplicationLocked(IApplicationThread thread,
         int pid, int callingUid, long startSeq) {
         //...
   try {
         AppDeathRecipient adr = new AppDeathRecipient(
                 app, pid, thread);
         thread.asBinder().linkToDeath(adr, 0);
         app.deathRecipient = adr;
     } catch (RemoteException e) {
         app.resetPackageList(mProcessStats);
         mProcessList.startProcessLocked(app,
                 new HostingRecord("link fail", processName));
         return false;
     }
   //...
}

當(dāng)有binder服務(wù)死亡眶明,會(huì)調(diào)用 AppDeathRecipient 的 binderDied()方法:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
      private final class AppDeathRecipient implements IBinder.DeathRecipient {
          final ProcessRecord mApp;
          final int mPid;
          final IApplicationThread mAppThread;
  
          AppDeathRecipient(ProcessRecord app, int pid,
                  IApplicationThread thread) {
              if (DEBUG_ALL) Slog.v(
                  TAG, "New death recipient " + this
                  + " for thread " + thread.asBinder());
              mApp = app;
              mPid = pid;
              mAppThread = thread;
          }
  
          @Override
          public void binderDied() {
              if (DEBUG_ALL) Slog.v(
                  TAG, "Death received in " + this
                  + " for thread " + mAppThread.asBinder());
              synchronized(ActivityManagerService.this) {
                  appDiedLocked(mApp, mPid, mAppThread, true);
              }
          }
      }
@GuardedBy("this")
final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
      boolean fromBinderDied) {
......
   // 如果沒有被殺,再次殺app
  if (!app.killed) {
      if (!fromBinderDied) {
          killProcessQuiet(pid);
      }
      ProcessList.killProcessGroup(app.uid, pid);
      app.killed = true;
  }
......
      //  調(diào)用 handleAppDiedLocked
      handleAppDiedLocked(app, false, true);
......
  }
  //...
}
final void handleAppDiedLocked(ProcessRecord app,
         boolean restarting, boolean allowRestart) {
     int pid = app.pid;
     // 清理service筐高、broadcastreveiver搜囱、contentprovider等信息
     boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
             false /*replacingPid*/);
     if (!kept && !restarting) {
     // 移除崩潰進(jìn)程在AMS中的代表 ProcessRecord
         removeLruProcessLocked(app);
         if (pid > 0) {
             ProcessList.remove(pid);
         }
     }

     if (mProfileData.getProfileProc() == app) {
         clearProfilerLocked();
     }
      // 繼續(xù)調(diào)用 atm的 handleAppDied
     mAtmInternal.handleAppDied(app.getWindowProcessController(), restarting, () -> {
         Slog.w(TAG, "Crash of app " + app.processName
                 + " running instrumentation " + app.getActiveInstrumentation().mClass);
         Bundle info = new Bundle();
         info.putString("shortMsg", "Process crashed.");
         finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
     });
 }

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public void handleAppDied(WindowProcessController wpc, boolean restarting,
       Runnable finishInstrumentationCallback) {
   synchronized (mGlobalLockWithoutBoost) {
       // Remove this application's activities from active lists.
       // 清理activities相關(guān)信息
       boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc);

       wpc.clearRecentTasks();
       wpc.clearActivities();

       if (wpc.isInstrumenting()) {
           finishInstrumentationCallback.run();
       }

       if (!restarting && hasVisibleActivities) {
           mWindowManager.deferSurfaceLayout();
           try {
               if (!mRootActivityContainer.resumeFocusedStacksTopActivities()) {
                   // If there was nothing to resume, and we are not already restarting
                   // this process, but there is a visible activity that is hosted by the
                   // process...then make sure all visible activities are running, taking
                   // care of restarting this process.
                   // 確保恢復(fù)頂部的activity
                   mRootActivityContainer.ensureActivitiesVisible(null, 0,
                           !PRESERVE_WINDOWS);
               }
           } finally {
              // windows相關(guān)
               mWindowManager.continueSurfaceLayout();
           }
       }
   }
}

當(dāng)App發(fā)生崩潰后柑土,除了彈出對(duì)話框蜀肘,發(fā)送kill命令殺掉自身后。AMS還會(huì)收到App進(jìn)程的Binder服務(wù)死亡通知稽屏,只有當(dāng)走完Binder的 binderDied()流程后扮宠,整個(gè)崩潰流程才算真正結(jié)束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狐榔,一起剝皮案震驚了整個(gè)濱河市坛增,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌薄腻,老刑警劉巖收捣,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異被廓,居然都是意外死亡坏晦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門嫁乘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昆婿,“玉大人,你說我怎么就攤上這事蜓斧〔智” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵挎春,是天一觀的道長棍厂。 經(jīng)常有香客問我躺苦,道長张症,這世上最難降的妖魔是什么九杂? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮脚线,結(jié)果婚禮上搁胆,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好渠旁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布攀例。 她就那樣靜靜地躺著,像睡著了一般顾腊。 火紅的嫁衣襯著肌膚如雪粤铭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天杂靶,我揣著相機(jī)與錄音梆惯,去河邊找鬼。 笑死伪煤,一個(gè)胖子當(dāng)著我的面吹牛加袋,可吹牛的內(nèi)容都是我干的凛辣。 我是一名探鬼主播抱既,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼扁誓!你這毒婦竟也來了防泵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蝗敢,失蹤者是張志新(化名)和其女友劉穎捷泞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寿谴,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锁右,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了讶泰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咏瑟。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖痪署,靈堂內(nèi)的尸體忽然破棺而出码泞,到底是詐尸還是另有隱情,我是刑警寧澤狼犯,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布余寥,位于F島的核電站,受9級(jí)特大地震影響悯森,放射性物質(zhì)發(fā)生泄漏宋舷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一瓢姻、第九天 我趴在偏房一處隱蔽的房頂上張望祝蝠。 院中可真熱鬧,春花似錦、人聲如沸续膳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坟岔。三九已至谒兄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間社付,已是汗流浹背承疲。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸥咖,地道東北人燕鸽。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像啼辣,于是被迫代替她去往敵國和親啊研。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容