Android開機log分析
分析開機log,一是可以理一下android啓動流程,二是可以通過log定位錯誤
首先,我們給出一張比較全面的Android系統啓動圖
根據上述Android的啓動框圖,我們可以順序地列出Android系統啓動中涉及的幾個關鍵步驟:
(1) Linux內核的啓動
(2) Init程序啓動,並啓動各個本地服務(如 healthd, debuggerd等)
(3) Zygote進程啓動
(4) Zygote進程初始化工作(preload class/resource)
(5) SystemServer進程啓動,並啓動各個Java服務(如 ActivityManager, PackageManager等 )
(7) 啓動結束的標誌點
如果我們能夠從啓動log信息中找出上述這些關鍵步驟的時間節點,也就可以很清晰地得到Android系統啓動過程中各個模塊消耗的時間了,在做系統啓動優化時,也就知道該去優化哪些耗時的模塊了,同樣,在分析系統啓動bug的時候,也就知道到底哪裏出了問題了。
分析log信息
(1) Linux內核的啓動
Linux內核啓動的log都位於dmesg.txt文件中,從log文件開始直到出現下面這條消息則標誌着Linux內核已經完成了啓動:
"Freeing init memory"
因此,我們從dmesg.txt文件中即可得到APQ8064開發板的Linux內核啓動只用了6.613s,如圖所示:
(2) Init程序啓動,並啓動各個本地服務(如 healthd, debuggerd等)
Init程序的log信息也位於dmesg.txt文件中,我們可以通過檢索“init”找到該程序的打印消息。
通過檢索“init starting”,我們可以找到init進程啓動了哪些本地服務,如:
(3) Zygote進程啓動
zygote進程是在init進程中啓動的,因此,我們從上面init進程的輸出log中,檢索"zygote"就可以找到zygote進程何時啓動的,如圖所示:
(4) Zygote進程初始化工作(preload class/resource)
Zygote進程所輸出的log信息被放到/dev/log/main文件中了,因此,我們需要檢索main.txt得到Zygote的log信息。
由於後續所有的Android應用程序都是從Zygote進程fork出來的,Android系統爲了提高應用程序的啓動速度,會在Zygote進程初始化過程中加載一些常用的java class和資源文件到進程的內存中,從而共享常用的class和resourse資源。這個過程我們可以通過檢索"preload"標籤得到這個過程所消耗的時間,如圖所示:
(5) SystemServer進程啓動,並啓動各個Java服務(如 ActivityManager, PackageManager等 )
Zygote完成了初始化工作後就啓動SystemServer進程了,SystemServer進程的log信息被放到了/dev/log/system文件中了,因此,我們需要檢索system.txt文件得到SystemServer的log信息,如圖所示:
(7) 啓動結束的標誌點
《Android內核開發:如何統計系統啓動時間》這篇文章已經詳細地介紹瞭如何找到啓動結束的時間,這裏選取其中一種方法再複述一遍,就是檢索dmesg文件的 "boot_completed" 標誌,如圖所示,我們知道了整個系統一共耗時29.913s完成啓動:
2.、下面列舉一些常見android程序發生錯誤時拋出的異常,查找關鍵字xxxException可以快速定位android層錯誤以及原因:
- Java.lang.NullPointerException:
- 空指針異常
- java.lang.ClassNotFoundException:
- 找不到類拋出的異常
- java.lang.ArithmeticException:
- 一個整數“除以零”時拋出的異常
- java.lang.ArrayIndexOutOfBoundsException:
- 數組越界訪問以後拋出的異常
- java.lang.IllegalArgumentException:
- 傳入非法參數拋出的異常
- java.lang.IllegalAccessException:
- 當應用程序要調用一個類,但當前的方法即沒有對該類的訪問權限便會出現這個異常
- java.lang.SecturityException:
- 安全異常。由安全管理器拋出,用於指示違反安全情況的異常
- java.lang.RuntimeException
- 運行時異常。是所有Java虛擬機正常操作期間可以被拋出的異常的父類。
- java.lang.NumberFormatException:
- 字符串轉換爲數字異常:
- java.lang.StackOverflowError:
- 堆棧溢出錯誤。當一個應用遞歸調用的層次太深而導致堆棧溢出時拋出該錯誤。
- java.lang.RuntimeException
- java.lang.OutOfMemoryError:
- 內存不足錯誤。當可用內存不足以讓Java虛擬機分配給一個對象時拋出該錯誤。
- java.lang.IOException:
- 輸入輸出異常
- java.lang.AbstractMethodError:
- 抽象方法錯誤。當應用試圖調用抽象方法時拋出。
- java.lang.ClassFormatError:
- 類格式錯誤。當Java虛擬機試圖從一個文件中讀取Java類,而檢測到該文件的內容不符合類的有效格式時拋出。
- java.lang.InstantiationError:
- 實例化錯誤。當一個應用試圖通過Java的new操作符構造一個抽象類或者接口時拋出該異常.
- java.lang.InternalError:內部錯誤。用於指示Java虛擬機發生了內部錯誤。
- java.lang.NoSuchMethodError
- 方法不存在錯誤。當應用試圖調用某類的某個方法,而該類的定義中沒有該方法的定義時拋出該錯誤。
- java.lang.VirtualMachineError
- 虛擬機錯誤。用於指示虛擬機被破壞或者繼續執行操作所需的資源不足的情況
- java.lang.ClassCastException
- 類造型異常。假設有類A和B(A不是B的父類或子類),O是A的實例,那麼當強制將O構造爲類B的實例時拋出該異常。該異常經常被稱爲強制類型轉換異常。
- java.lang.InterruptedException
- 被中止異常。當某個線程處於長時間的等待、休眠或其他暫停狀態,而此時其他的線程通過Thread的interrupt方法終止該線程時拋出該異常。
- java.lang.IllegalStateException
- 違法的狀態異常。當在Java環境和應用尚未處於某個方法的合法調用狀態,而調用了該方法時,拋出該異常。
- java.lang.ExceptionInInitializerError
- 初始化程序錯誤。當執行一個類的靜態初始化程序的過程中,發生了異常時拋出。靜態初始化程序是指直接包含於類中的static語句段。