Unable to launch com.* for service Intent { cmp=com.*/.* }: process is bad

 最近的項目需要用到服務端收集客戶端崩潰的詳細異常log數據:

 

之前也做過,感覺很輕鬆,沒想到遇到問題了,還糾結了半天:

 以下是關鍵log日誌

05-04 20:28:42.409: W/ActivityManager(374): Process com.example.service has crashed too many times: killing!
05-04 20:28:42.409: I/ActivityManager(374): Killing proc 20556:com.example.service/u0a10080: crash
05-04 20:28:43.323: W/ActivityManager(374): Unable to launch app com.example.service/10080 for service Intent { cmp=com.example.service/.service.TestService }: process is bad

 

問題介紹:

a、帶界面的應用,當應用擁有當前界面時發生RuntimeException,可以被alarm和BroadcastReceiver喚醒;

b、統計器後臺運行:產生RuntimeException之後再也起不來了(不可以被alarm和BroadcastReceiver再次喚醒);

 

問題查找過程:

推薦一個在線查看源碼的網站,很方便

http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/

 

1、 關鍵詞搜索:process is bad

2、發現出處

 class: com.android.server.am.ActivityManagerService 
    method: private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
        String name, IBinder token, boolean stable, int userId);

    具體位置:

   

ProcessRecord proc = startProcessLocked(cpi.processName,
        cpr.appInfo, false, 0, "content provider",
        new ComponentName(cpi.applicationInfo.packageName,
                cpi.name), false, false);
if (proc == null) {
    Slog.w(TAG, "Unable to launch app "
            + cpi.applicationInfo.packageName + "/"
            + cpi.applicationInfo.uid + " for provider "
            + name + ": process is bad");
    return null;
}

 

 

 

 

3、繼續跟蹤 com.android.server.am.ActivityManagerService 的 startProcessLocked ,原因就在裏頭;

    

 

 

原因:

參考:

 

	class :	com.android.server.am.ActivityManagerService
	method: final ProcessRecordstartProcessLocked(String processName,
			ApplicationInfo info, boolean knownToBeDead, int intentFlags,
			String hostingType, ComponentName hostingName,
			boolean allowWhileBooting, boolean isolated) {}

 
   程序發生RuntimeException,被crash掉,如果被重新起來,這個時候判斷是否是後臺應用,如果是後臺應用則silently fail.

 

 

   關鍵代碼:紅色標記註釋

 

	if (!isolated) {
    if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
        // If we are in the background, then check to see if this process
        // is bad.  If so, we will just silently fail.
        if (mBadProcesses.get(info.processName, info.uid) != null) {
            if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                    + "/" + info.processName);
            return null;
        }
    } else {
        // When the user is explicitly starting a process, then clear its
        // crash count so that we won't make it bad until they see at
        // least one crash dialog again, and make the process good again
        // if it had been bad.
        if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                + "/" + info.processName);
        mProcessCrashTimes.remove(info.processName, info.uid);
        if (mBadProcesses.get(info.processName, info.uid) != null) {
            EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                    UserHandle.getUserId(info.uid), info.uid,
                    info.processName);
            mBadProcesses.remove(info.processName, info.uid);
            if (app != null) {
                app.bad = false;
            }
        }
    }

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章