導航:首頁 > 操作系統 > android系統啟動流程

android系統啟動流程

發布時間:2022-10-01 07:17:09

A. Activity的啟動流程

開發中我們會調用startActivity來啟動一個Activity,最終會調到 startActivityForResult

Instrumentationandroid系統裡面的一套控制方法或者「鉤子」。這些鉤子可以在正常的生命周期(正常是由操作系統控制的)之外控制Android控制項的運行。

Application和Activity的所有生命周期中,都會先調用Instrumentation提供的相應方法(如callActivityOnCreate,callApplicationOnCreate,newActivity,callActivityOnNewIntent)

Instrumentation.execStartActivity

ActivityTaskManager.getService()返回了一個IActivityTaskManager,拿到的是ATMS的代理對象,跨進程調用了ATMS的startActivity方法。

ActivityStarter.startActivityMayWait

ActivityStarter中做了一系列的調用(收集Intent信息,處理startActivityForResult,做一些校驗判斷等),最終進入startActivityUnchecked。

startActivityUnchecked

startActivityUnchecked中處理了關於Activity啟動模式的處理,接著真正的resume我們的Activity

這里會先判斷應用進程是否創建,創建了就進入 realStartActivityLocked ,沒創建就會調用 ActivityManagerInternal.startProcess

①熱啟動realStartActivityLocked

接著看ActivityThread中接收並處理消息的handleMessage

前面realStartActivityLocked方法中通過addCallback,傳入參數LaunchActivityItem。executeCallbacks方法中取出callbacks集合中的LaunchActivityItem,並調用其execute方法

handleLaunchActivity

②冷啟動創建應用進程ActivityManagerInternal.startProcess

ActivityManagerInternal的實現類是AMS中的LocalService,AMS通過Socket與Zygote通信,fork出App進程,app進程創建後,會執行ActivityThread的main方法(Android進程入口方法)

調用ActivityThread的attach

[4]thread.bindApplication 這是一個binder通信的過程

ActivityThread內部的Handler接收到BIND_APPLICATION消息

回到上面attachApplicationLocked的mAtmInternal.attachApplication,調用ATMS的attachApplication

看到了似曾相識的realStartActivityLocked,後面流程和之前一樣。Activity啟動流程分析完畢。

總結

1)與Activity管理有關的類:

ActivityRecord :歷史棧中的一個條目,代表一個Activity

TaskRecord :內部維護了一個ArrayList<ActivityRecord> ,來保存ActivityRecord

ActivityStack :內部維護了一個ArrayList<TaskRecord>,用來管理TaskRecord

ActivityStackSupervisor :用來管理ActivityStack的

2)Activity啟動流程

B. Android應用程序啟動流程總結

AMS主要功能:
AMS是Android中最核心的服務,主要負責系統中四大組件的啟動、切換、調度及應用進程的管理和調度等工作。還負責啟動或殺死應用程序的進程。

WMS主要功能:
為所有窗口分配Surface。
管理Surface的顯示順序、尺寸、位置。
管理窗口動畫。
輸入系統相關:WMS是派發系統按鍵和觸摸消息的最佳人選,當接收到一個觸摸事件,它需要尋找一個最合適的窗口來處理消息。

PWS主要功能:
PMS 用來管理跟蹤所有應用APK,包括安裝,卸載,解析,控制許可權等。

SystemServer也是一個進程,包括AMS、PMS、WMS等等。

zygote意為「受精卵「。Android是基於Linux系統的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。

App進程是用戶點擊桌面icon時,通過Launcher進程請求SystemServer,再調用Zygote孵化的。

①點擊啟動一個App,Launcher進程採用Binder IPC向ActivityManagerService發起startActivity請求;

②ActivityManagerService接收到請求後,向zygote進程發送創建進程的請求;

③Zygote進程fork出新的子進程,即App進程;

④App進程通過Binder IPC向sytem_server進程發起綁定Application請求;

⑤system_server進程在收到請求後,進行一系列准備工作後,再通過binder IPC向App進程發送scheleLaunchActivity請求;

⑥App進程的binder線程(ApplicationThread)在收到請求後,通過handler向主線程發送LAUNCH_ACTIVITY消息;

⑦主線程在收到Message後,通過發射機制創建目標Activity,並回調Activity.onCreate()等方法。

⑧到此,App便正式啟動,開始進入Activity生命周期,執行完onCreate/onStart/onResume方法,UI渲染結束後便可以看到App的主界面。

備註:
Launcher,PMS,Zygote,App進程是三個獨立的進程,相互通信就需要使用進程間通信機制。與Zygote通信是使用的socket通信,Launcher,PMS,App進程間使用的是Binder機制。

C. Android的文件系統和分區表誰能給我詳細地講一講

Android系統啟動流程如下:
1、啟動電源以及系統啟動
當電源按下時引導晶元代碼從預定義的地方(固化在ROM)開始執行。載入引導程序BootLoader到RAM,然後執行。
2、引導程序BootLoader
引導程序BootLoader是在Android操作系統開始運行前的一個小程序,它的主要作用使把系統OS拉起來並運行。
3、Linux內核啟動
當內核啟動時,設置緩存、被保護存儲器、計劃列表、載入驅動。當內核完成系統設置時,它首先在系統文件中尋找init.rc文件,並啟動init進程。
4、init進程啟動
初始化和啟動屬性服務,並且啟動Zygote進程。
5、Zygote進程啟動
創建java虛擬機並為Java虛擬機注冊JNI方法,創建伺服器端Socket,啟動SystemServer進程。
6、SystemServer進程啟動
啟動Binder線程池和SystemServiceManager,並且啟動各種系統服務。
7、Launcher啟動
被SystemServer進程啟動的AMS會啟動Launcher,Launcher啟動會將已安裝的快捷圖標顯示在界面上。

D. android activitythread 怎麼啟動

首先看一下Android系統的啟動流程: bootloader 引導程序 kernel 內核 init init初始化(這個大家都比較熟悉了,不要多說) loads several daemons and services, including zygote see /init.rc and init..rc zygote 這個是佔用時間最多的

E. android preload怎麼用

首先看一下Android系統的啟動流程:
bootloader
引導程序
kernel
內核
init
init初始化(這個大家都比較熟悉了,不要多說)
loads several daemons and services, including zygote
see /init.rc and init.<platform>.rc
zygote

這個是佔用時間最多的,重點修理對象
preloads classes
裝載了一千多個類,媽呀!!!
starts package manager 掃描package(下面詳細介紹)
service manager
start services (啟動多個服務)
從實際的測試數據來看,有兩個地方時最耗時間的,一個是zygote的裝載一千多個類和初始化堆棧的過程,用了20秒左右。另一個是掃描
/system/app,
/system/framework,
/data/app,
/data/app-private.
這幾個目錄下面的package用了大概10秒,所以我們重點能夠修理的就是這兩個老大的。
一、首先是調試工具的使用,可以測試哪些類和那些過程佔用了多少時間,
主要工具為
stopwatch
Message loggers
grabserial
printk times
logcat
Android自帶
bootchart
strace
AOSP的一部分(Eclair及以上版本)
使用例子
在init.rc中為了調試zygote

F. reboot+recovery,quiescent

摘要 項目中需要處理Android的原生開機動畫,一定條件下還需要做到靜默重啟(android系統啟動進入到桌面前,屏幕保持完全沒有亮度的狀態)。因為項目使用的rom是MTK平台支持,一開始並不知道Android 的QUIESCENT_REBOOT模式,所以自己想辦法實現了此功能,詳細見博客:基於Q的Android開機動畫。因為後續Linux啟用了SELinux增強了許可權限制,原有的方案因為許可權限制了文件的執行和讀寫,需要進行比較大的變動。後來,學習了下Android 的QUIESCENT_REBOOT模式,並把它用到了項目中解決了問題。這里介紹下QUIESCENT_REBOOT模式原理。

G. Android之Activity全面解析,有些知識點容易忘記

Activity作為安卓四大組件之一,是最重要也是用得最多的組件,涉及的知識點非常多,有些知識點平時開發很少用到,但在某些場景下需要特別注意,本文詳細整理了Activity涉及的知識點,供開發參考。

針對Activity可以提出很多問題,如:
Activity 的生命周期?
Activity 之間的通信方式?
Activity 各種情況下的生命周期?
橫豎屏切換時 Activity 的生命周期?
前台切換到後台,然後再回到前台時 Activity 的生命周期?
彈出 Dialog 的時候按 Home 鍵時 Activity 的生命周期?
兩個Activity之間跳轉時的生命周期?
下拉狀態欄時 Activity 的生命周期?
Activity 與 Fragment 之間生命周期比較?
Activity 的四種 LaunchMode(啟動模式)的區別?
Activity 狀態保存與恢復?
Activity的轉場動畫有哪些實現方式?
Activity的生命周期中怎麼獲取控制項寬高?
onNewIntent的執行時機?
如何連續退出多個Activity?

如何把Acitivty設置成Dialog樣式 ,android:theme="@android:style/Theme.Dialog"

關於橫豎屏切換的生命周期,對應不同的手機,由於廠商定製的原因,會有不同的效果,如設置了configChanges="orientation」在有些手機會執行各個生命周期,但有些手機卻不會執行。
網上常見的結論如下:

但實際的測試如下:

可以看出,不同廠商的手機切屏生命周期會有差異。
從API 13以上,當設備在橫豎切屏時,「屏幕尺寸」也會發生變化,因此為了杜絕切屏導致頁面銷毀重建,需要加上screenSize,使用設置4,即 android:configChanges="orientation|keyboardHidden|screenSize" .

Activity的四種狀態如下:

在activity處於paused或者stoped狀態下,如果系統內存緊張,可能會被銷毀,當重回該activity時會重建,正常返回和被回收後返回的生命周期如下:

如果是回收後返回,onCreate的參數savedInstanceState不為空。

有哪些場景會觸發onNewIntent回調呢?跟啟動模式有關,首先該Activity實例已經存在,再次啟動才可能觸發。一種情況是啟動模式是singleTask或者singleInstance,無論該activity在棧中哪個位置,都會觸發onNewIntent回調,並且把上面其他acitivity移除,另一種情況是啟動模式是singleTop或者以FLAG_ACTIVITY_SINGLE_TOP啟動,並且該activity實例在棧頂,會觸發onNewIntent,如果不在棧頂是重新創建的,不會觸發。

在實際業務開發中,往往碰到需要連續退出多個activity實例,下面整理了幾種常見方法:

● 發送特定廣播
1、在需要處理連續退出的activity注冊該特定廣播;
2、發起退出的activity發送該特定廣播;
3、接收到該廣播的activity 調用finish結束頁面。
● 遞歸退出
1、用startActivityForResult啟動新的activity;
2、前一個頁面finish時,觸發onActvityResult回調,再根據requestCode和resultCode處理是否finish,達到遞歸退出的效果。
● FLAG_ACTIVITY_CLEAR_TOP
通過intent.setFlag(Intent.FLAG_ACTIVITY_CLEAR_TOP)啟動新activity,如果棧中已經有該實例,則會把該activity之上的所有activity關閉,達到singleTop啟動模式的效果。
● 自定義activity棧
1、自定義activity列表,新打開activity則加入棧中,關閉則移除棧;
2、需要退出多個activity時,則循環從棧中移除activity實例,並調用finish。

在討論Activity啟動模式經常提到任務棧,那到底什麼是任務棧?
任務是一個Activity的集合,它使用棧的方式來管理其中的Activity,這個棧又被稱為返回棧(back stack),棧中Activity的順序就是按照它們被打開的順序依次存放的。返回棧是一個典型的後進先出(last in, first out)的數據結構。下圖通過時間線的方式非常清晰地向我們展示了多個Activity在返回棧當中的狀態變化:

taskAffinity 任務相關性,可以用於指定一個Activity更加願意依附於哪一個任務,在默認情況下,同一個應用程序中的所有Activity都具有相同的affinity, 名字為應用的包名。當然了,我們可以為每個 Activity 都單獨指定 taskAffinity 屬性(不與包名相同)。taskAffinity 屬性主要和 singleTask 啟動模式和 allowTaskReparenting 屬性配對使用,在其他情況下沒有意義。
taskAffinity 有下面兩種應用場景:

分為顯示啟動和隱式啟動。
(1)顯示啟動
直接指定待調整的Activity類名。

(2)隱式啟動
Intent 能夠匹配目標組件的 IntentFilter 中所設置的過濾信息,如果不匹配將無法啟動目標 Activity。IntentFilter 的過濾信息有 action、category、data。
IntentFilter 需要注意的地方有以下:
● 一個 Activity 中可以有多個 intent-filter
● 一個 intent-filter 同時可以有多個 action、category、data
● 一個 Intent 只要能匹配任何一組 intent-filter 即可啟動對應 Activity
● 新建的 Activity 必須加上以下這句,代表能夠接收隱式調用
<category android:name="android.intent.category.DEFAULT" />

只要匹配一個action即可跳轉,注意的是action要區分大小寫。

規則:如果intent中有category,則所有的都能匹配到intent-filter中的category,intent中的category數量可用少於intent-filter中的。另外,單獨設置category是無法匹配activity的,因為category屬性是一個執行Action的附加信息。

intent不添加category會匹配默認的,即 「android:intent.category.DEFAULT」
如果上面例子,如果去掉intent.setAction("action_name"),則會拋出異常:

規則:類似action,但data有復雜的結構,只要匹配一個data並且與data中所有屬性都一致就能匹配到Activity,只要有1個屬性不匹配,都無法找到activity。
data的結構:

data 主要是由 URI 和 mimeType 組成的。
URI 可配置很多信息,的結構如下:

與url類似,例如:

mineType:指資源類型包括文本、圖片、音視頻等等,例如:text/plain、 image/jpeg、video/* 等

下面看下data匹配的例子:
只匹配scheme

只匹配scheme也是能匹配到activity的。

匹配scheme、host、port
將上面的data改為

匹配mineType

如果有mineType,則不能僅設置setData或setMineType了,因為setData會把mineType置為null,而setMineType會把data置為null,導致永遠無法匹配到activity,要使用setDataAndType。

使用scheme的默認值contentfile

注意該方法需要在startAtivity方法或者是finish方法調用之後立即執行,不能延遲,但可以在子線程執行。

而在windowAnimationStyle中存在四種動畫:
activityOpenEnterAnimation // 打開新的Activity並進入新的Activity展示的動畫
activityOpenExitAnimation // 打開新的Activity並銷毀之前的Activity展示的動畫
activityCloseEnterAnimation //關閉當前Activity進入上一個Activity展示的動畫
activityCloseExitAnimation // 關閉當前Activity時展示的動畫

overridePendingTransition的方式比較生硬,方法也比較老舊了,不適用於MD風格,google提供了新的轉場動畫ActivityOptions,並提供了兼容包ActivityOptionsCompat。

我們知道在onCreate和onResume裡面直接獲取到控制項寬高為0,那有什麼辦法獲取到控制項的實際寬高?只要有onWindowFocusChanged、view.post、ViewTreeObserver三種方式獲取。

當用戶點擊桌面圖標啟動APP時,背後的流程如下:

我們看到的手機桌面是Launch程序的界面,點擊應用圖標會觸發點擊事件,調用startActivity(intent),然後通過Binder IPC機制,與ActivityManagerService(AMS)通訊,AMS執行一系列操作,最終啟動目前應用,大概流程如下:

通過PackageManager的resolveIntent()收集跳轉intent對象的指向信息,然後通過grantUriPermissionLocked()方法來驗證用戶是否有足夠的許可權去調用該intent對象指向的Activity。如果有許可權,則在新的task中啟動目標activity,如果發現沒有進程,則先創建進程。

如果進程不存在,AMS會調用startProcessLocked創建新的進程,在該方法中,會通過socket的通訊方式通知zygote進程孵化新的進程並返回pid,在新的進程中會初始化ActivityThread,並依次調用Looper.prepareLoop()和Looper.loop()來開啟消息循環。

創建好進程後下一步要將Application和進程綁定起來,AMS會調用上一節創建的ActivityThread對象的bindAppliction方法完成綁定工作,該方法會發送一條BIND_APPLICATION的消息,最終會調用handleBindApplication方法處理消息,並調用makeApplication方法處理消息,載入APP的classes到內存中。

通過前面的步驟,系統已經擁有了該Application的進程,後續的啟動則是從已存在其他進程中啟動Acitivity,即調用realStartAcitvityLocked,該方法會調用Application的主線程對象ActivityThread的sheleLaunchActivity方法,在方法中會發送LAUNCH_ACTIVITY到消息隊列,最終通過handleLaunchActivity處理消息,完成Acitivty的啟動。

Activity
Activity 的 36 大難點,你會幾個?「建議收藏」
[譯]Android Application啟動流程分析

H. 全面解析Activity: Activity的工作過程

本文將對Activity的工作過程進行分析。

主要學習以下內容:

(1)系統內部是如何啟動一個Activity的?

(2)新Activity的對象是何時創建的?

(3)Activity的各個生命周日是被系統何時回調的?

Activity啟動流程分兩種,一種是啟動正在運行的app的Activity,即啟動子Activity。如無特殊聲明默認和啟動該activity的activity處於同一進程。如果有聲明在一個新的進程中,則處於兩個進程。另一種是打開新的app,即為Launcher啟動新的Activity。後邊啟動Activity的流程是一樣的,區別是前邊判斷進程是否存在的那部分。

Activity的啟動流程整體如下:

一.Activity啟動階段

(一)涉及到的概念

進程:Android系統為每個APP分配至少一個進程

IPC:跨進程通信,Android中採用Binder機制。

(二)涉及到的類

ActivityStack:Activity在AMS的棧管理,用來記錄已經啟動的Activity的先後關系,狀態信息等。通過ActivityStack決定是否需要啟動新的進程。

ActivitySupervisor:管理 activity 任務棧

ActivityThread:ActivityThread 運行在UI線程(主線程),App的真正入口。

ApplicationThread:用來實現AMS和ActivityThread之間的交互。

ApplicationThreadProxy:ApplicationThread 在服務端的代理。AMS就是通過該代理與ActivityThread進行通信的。

IActivityManager:繼承與IInterface介面,抽象出跨進程通信需要實現的功能

AMN:運行在server端(SystemServer進程)。實現了Binder類,具體功能由子類AMS實現。

AMS:AMN的子類,負責管理四大組件和進程,包括生命周期和狀態切換。AMS因為要和ui交互,所以極其復雜,涉及window。

AMP:AMS的client端代理(app進程)。了解Binder知識可以比較容易理解server端的stub和client端的proxy。AMP和AMS通過Binder通信。

Instrumentation:儀表盤,負責調用Activity和Application生命周期。測試用到這個類比較多。

(三)涉及到的進程

(1)Launcher所在的進程

(2)AMS所在的SystemServer進程

(3)要啟動的Activity所在的app進程

如果是啟動根Activity,就涉及上述三個進程。

如果是啟動子Activity,那麼就只涉及AMS進程和app所在進程。

(四)具體流程

Launcher:Launcher通知AMS要啟動activity。

startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity

AMS:PMS的resoveIntent驗證要啟動activity是否匹配。如果匹配,通過ApplicationThread發消息給Launcher所在的主線程,暫停當前Activity(即Launcher)。

暫停完,在該activity還不可見時,通知AMS,根據要啟動的Activity配置ActivityStack。然後判斷要啟動的Activity進程是否存在?

存在:發送消息LAUNCH_ACTIVITY給需要啟動的Activity主線程,執行handleLaunchActivity

不存在:通過socket向zygote請求創建進程。進程啟動後,ActivityThread.attach

判斷Application是否存在,若不存在,通過LoadApk.makeApplication創建一個。在主線程中通過thread.attach方法來關聯ApplicationThread。

在通過ActivityStackSupervisor來獲取當前需要顯示的ActivityStack。

繼續通過ApplicationThread來發送消息給主線程的Handler來啟動Activity (handleLaunchActivity)。

handleLauchActivity:調用了performLauchActivity,里邊Instrumentation生成了新的activity對象,繼續調用activity生命周期。

IPC過程:

雙方都是通過對方的代理對象來進行通信。

1.app和AMS通信:app通過本進程的AMP和AMS進行Binder通信

2.AMS和新app通信:通過ApplicationThreadProxy來通信,並不直接和ActivityThread通信

(五)參考函數流程

Activity啟動流程(從Launcher開始):

第一階段: Launcher通知AMS要啟動新的Activity(在Launcher所在的進程執行)

第二階段:AMS先校驗一下Activity的正確性,如果正確的話,會暫存一下Activity的信息。然後,AMS會通知Launcher程序pause Activity(在AMS所在進程執行)

第三階段:pause Launcher的Activity,並通知AMS已經paused(在Launcher所在進程執行)

第四階段:檢查activity所在進程是否存在,如果存在,就直接通知這個進程,在該進程中啟動Activity;不存在的話,會調用Process.start創建一個新進程(執行在AMS進程)

第五階段: 創建ActivityThread實例,執行一些初始化操作,並綁定Application。如果Application不存在,會調用LoadedApk.makeApplication創建一個新的Application對象。之後進入Loop循環。(執行在新創建的app進程)

第六階段:處理新的應用進程發出的創建進程完成的通信請求,並通知新應用程序進程啟動目標Activity組件(執行在AMS進程)

第七階段: 載入MainActivity類,調用onCreate聲明周期方法(執行在新啟動的app進程)

從另一個角度下圖來概括:

下面簡要介紹一下啟動的過程:

        Step 1. 無論是通過Launcher來啟動Activity,還是通過Activity內部調用startActivity介面來啟動新的Activity,都通過Binder進程間通信進入到ActivityManagerService進程中,並且調用ActivityManagerService.startActivity介面; 

        Step 2. ActivityManagerService調用ActivityStack.startActivityMayWait來做准備要啟動的Activity的相關信息;

        Step 3. ActivityStack通知ApplicationThread要進行Activity啟動調度了,這里的ApplicationThread代表的是調用ActivityManagerService.startActivity介面的進程,對於通過點擊應用程序圖標的情景來說,這個進程就是Launcher了,而對於通過在Activity內部調用startActivity的情景來說,這個進程就是這個Activity所在的進程了;

        Step 4. ApplicationThread不執行真正的啟動操作,它通過調用ActivityManagerService.activityPaused介面進入到ActivityManagerService進程中,看看是否需要創建新的進程來啟動Activity;

        Step 5. 對於通過點擊應用程序圖標來啟動Activity的情景來說,ActivityManagerService在這一步中,會調用startProcessLocked來創建一個新的進程,而對於通過在Activity內部調用startActivity來啟動新的Activity來說,這一步是不需要執行的,因為新的Activity就在原來的Activity所在的進程中進行啟動;

        Step 6. ActivityManagerServic調用ApplicationThread.scheleLaunchActivity介面,通知相應的進程執行啟動Activity的操作;

        Step 7. ApplicationThread把這個啟動Activity的操作轉發給ActivityThread,ActivityThread通過ClassLoader導入相應的Activity類,然後把它啟動起來。

I. Android項目啟動的具體流程

先分析需求,確定要有什麼功能和要求,項目不大的話可以直接編代碼,如果比較的的項目最後先用UML設計下,想清楚思路再動手寫,編碼過程中當然也少不了單元測試,調試程序的功夫。順便提醒一下,Android3.0現在的份額還不大,多數都是2.2版本的,1.6的也不在少數,建議如果不是需要用到3.0的功能的話最好還是基於1.6版本的開發,增加兼容性

J. 怎樣提高android啟動速度

首先看一下Android系統的啟動流程:
bootloader
引導程序
kernel
內核
init
init初始化(這個大家都比較熟悉了,不要多說)
loads several daemons and services, including zygote
see /init.rc and init.<platform>.rc
zygote

這個是佔用時間最多的,重點修理對象
preloads classes
裝載了一千多個類,媽呀!!!
starts package manager 掃描package(下面詳細介紹)
service manager
start services (啟動多個服務)
從實際的測試數據來看,有兩個地方時最耗時間的,一個是zygote的裝載一千多個類和初始化堆棧的過程,用了20秒左右。另一個是掃描
/system/app,
/system/framework,
/data/app,
/data/app-private.
這幾個目錄下面的package用了大概10秒,所以我們重點能夠修理的就是這兩個老大的。
一、首先是調試工具的使用,可以測試哪些類和那些過程佔用了多少時間,
主要工具為
stopwatch
Message loggers
grabserial
printk times
logcat
Android自帶
bootchart
strace
AOSP的一部分(Eclair及以上版本)
使用例子
在init.rc中為了調試zygote

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server改為
service zygote /system/xbin/strace -tt -o/data/boot.strace /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

method tracer*
ftrace*
詳細使用可看提供的文檔和網頁介紹
上面的工具如果不用詳細的分析不一定都用到,也可以使用logcat就可以,在代碼中加一點計算時間和一些類的調試信息也可以達到很好效果。
二、zygote 裝載1千多個類
首先,我們可以添加一點調試信息,以獲得具體轉載情況。
diff --git a/core/java/com/Android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 404c513..f2b573c 100644
--- a/core/java/com/Android/internal/os/ZygoteInit.java
+++ b/core/java/com/Android/internal/os/ZygoteInit.java
@@ -259,6 +259,8 @@ public class ZygoteInit {
} else {
Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis();
+ long lastTime = SystemClock.uptimeMillis();
+ long nextTime = SystemClock.uptimeMillis();

// Drop root perms while running static initializers.
setEffectiveGroup(UNPRIVILEGED_GID);
@@ -292,12 +294,24 @@ public class ZygoteInit {
if (Config.LOGV) {
Log.v(TAG, "Preloading " + line + "...");
}
+ //if (count%5==0) {
+ // Log.v(TAG, "Preloading " + line + "...");
+ //}
+ Log.v(TAG, "Preloading " + line + "...");
Class.forName(line);
+ nextTime = SystemClock.uptimeMillis();
+ if (nextTime-lastTime >50) {
+ Log.i(TAG, "Preloading " + line + "... took " + (nextTime-lastTime) + "ms.");
+ }
+ lastTime = nextTime;
+
if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
if (Config.LOGV) {
Log.v(TAG,
" GC at " + Debug.getGlobalAllocSize());
}
+ Log.i(TAG,
+ " GC at " + Debug.getGlobalAllocSize());
runtime.gcSoftReferences();
runtime.runFinalizationSync();
Debug.resetGlobalAllocSize();
上面+代表添加的代碼,這樣就可以很容易的得到在裝載類的過程中具體裝載了哪些類,耗費了多久。具體裝載的類在文件platform/frameworks/base/ preloaded-classes
內容類似:
Android.R$styleable
Android.accounts.AccountMonitor
Android.accounts.AccountMonitor$AccountUpdater
Android.app.Activity
Android.app.ActivityGroup
Android.app.ActivityManager$MemoryInfo$1
Android.app.ActivityManagerNative
Android.app.ActivityManagerProxy
Android.app.ActivityThread
Android.app.ActivityThread$ActivityRecord
Android.app.ActivityThread$AppBindData
Android.app.ActivityThread$ApplicationThread
Android.app.ActivityThread$ContextCleanupInfo
Android.app.ActivityThread$GcIdler
Android.app.ActivityThread$H
Android.app.ActivityThread$Idler
而這個文件是由文件WritePreloadedClassFile.java中的WritePreloadedClassFile類自動生成
/**

* Writes /frameworks/base/preloaded-classes. Also updates

* {@link LoadedClass#preloaded} fields and writes over compiled log file.

*/
public class WritePreloadedClassFile
/**
* Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us.
*/
static final int MIN_LOAD_TIME_MICROS = 1250;//這個代表了裝載時間小於1250us即1.25ms的類將不予裝載,也許可以改這個參數減少一下類的裝載

//這里可以看到什麼樣的類會被裝載

A:啟動必須裝載的類,比如系統級的類

B:剛才說的裝載時間大於1.25ms的類

C:被使用一次以上或被應用裝載的類
仔細看看篩選類的具體實現,可以幫助我們認識哪些類比較重要,哪些可以去掉。
篩選規則是
第一 isPreloadable,
/**Reports if the given class should be preloaded. */
public static boolean isPreloadable(LoadedClass clazz) {
return clazz.systemClass && !EXCLUDED_CLASSES.contains(clazz.name);
}
意思是指除了EXCLUDED_CLASSES包含的類之外的所有系統裝載的類。
EXCLUDED_CLASSES包含
/**
* Classes which we shouldn't load from the Zygote.
*/
private static final Set<String> EXCLUDED_CLASSES
= new HashSet<String>(Arrays.asList(
// Binders
"Android.app.AlarmManager",
"Android.app.SearchManager",
"Android.os.FileObserver",
"com.Android.server.PackageManagerService$AppDirObserver",
// Threads
"Android.os.AsyncTask",
"Android.pim.ContactsAsyncHelper",
"java.lang.ProcessManager"
));
目前是跟Binders跟Threads有關的不會被預裝載。

第二 clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS裝載時間大於1.25ms。
第三 names.size() > 1 ,既是被processes一次以上的。
上面的都是指的system class,另外還有一些application class需要被裝載
規則是fromZygote而且不是服務
proc.fromZygote() && !Policy.isService(proc.name)

fromZygote指的除了com.Android.development的zygote類
public boolean fromZygote() {
return parent != null && parent.name.equals("zygote")
&& !name.equals("com.Android.development");
}

/除了常駐內存的服務

/**
* Long running services. These are restricted in their contribution to the
* preloader because their launch time is less critical.
*/
// TODO: Generate this automatically from package manager.
private static final Set<String> SERVICES = new HashSet<String>(Arrays.asList(
"system_server",
"com.google.process.content",
"Android.process.media",
"com.Android.bluetooth",
"com.Android.calendar",
"com.Android.inputmethod.latin",
"com.Android.phone",
"com.google.Android.apps.maps.FriendService", // pre froyo
"com.google.Android.apps.maps:FriendService", // froyo
"com.google.Android.apps.maps.LocationFriendService",
"com.google.Android.deskclock",
"com.google.process.gapps",
"Android.tts"
));
好了。要轉載的就是這些類了。雖然preloaded- classes是在下載源碼的時候已經確定了的,也就是對我們來說WritePreloadedClassFile類是沒用到的,我們可以做的就是在 preloaded-classes文件中,把不預裝載的類去掉,試了把所有類去掉,啟動確實很快跳過那個地方,但是啟動HOME的時候就會很慢了。所以最好的方法就是只去掉那些沒怎麼用到的,不過要小心處理。至於該去掉哪些,還在摸索,稍後跟大家分享。有興趣的朋友可以先把preloaded- classes這個文件裡面全部清空,啟動快了很多,但在啟動apk的時候會慢了點。當然了,也可以把Android相關的類全部去掉,剩下java的類,試過了也是可以提高速度。
三,系統服務初始化和package 掃描

在啟動系統服務的init2()時會啟動應用層(Java層)的所有服務。
public static void main(String[] args) {

System.loadLibrary("Android_servers");
init1(args); //init1 初始化,完成之後會回調init2()
}

在init2()中會啟動一個線程來啟動所有服務
public static final void init2() {
Log.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("Android.server.ServerThread");
thr.start();
}

class ServerThread extends Thread {
。。。
public void run() {
。。。
關鍵服務:
ServiceManager.addService("entropy", new EntropyService());
ServiceManager.addService(Context.POWER_SERVICE, power);
context = ActivityManagerService.main(factoryTest);
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));

PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);//apk掃描的服務
ServiceManager.addService(Context.ACCOUNT_SERVICE,
new AccountManagerService(context));
ContentService.main(context,
factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);
battery = new BatteryService(context);
ServiceManager.addService("battery", battery);

hardware = new HardwareService(context);
ServiceManager.addService("hardware", hardware);
AlarmManagerService alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);
ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));

WindowManagerService.main(context, power,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);

閱讀全文

與android系統啟動流程相關的資料

熱點內容
程序員用得到數字區嗎 瀏覽:174
python求商 瀏覽:477
ipad能用c語言編譯器嗎 瀏覽:561
軟泥解壓球最新版 瀏覽:998
4萬程序員辭職創業 瀏覽:759
thinkingphp 瀏覽:597
安卓相冊移動文件夾 瀏覽:6
耳朵清潔解壓聲控99的人都睡得著 瀏覽:205
叉車出租網站源碼 瀏覽:874
共享單車的app是什麼 瀏覽:408
不帶gui的伺服器什麼意思 瀏覽:373
金剛經及PDF 瀏覽:102
php中冒號 瀏覽:358
php5432 瀏覽:352
命令在哪使用 瀏覽:172
php獲取網頁元素 瀏覽:708
為什麼需要硬體驅動編譯 瀏覽:885
pm編程怎樣看導柱孔對不對稱 瀏覽:138
農業大學選課找不到伺服器怎麼辦 瀏覽:660
路由配置網關命令 瀏覽:935