一、包名
android.app.Instrumentation
這裏研究AMS中的Instrumentation類,當然在PMS的PackagePaser中也有同名的內部類(還有Activity, Service, Provider等),它們是PMS用於解析應用應用的Manifest文件的中間類,不在本次討論之列。
二、概述
Instrument, 儀器,樂器,工具。Instrumentation, 儀器化,使用儀器。Android源碼是google工程師用英文寫的,所以對於每一個類的命名也許只有身處他們的語言環境下才真正理解他們所要表達的含義,經過翻譯也許能幫我們稍微體會一點他們當時命名這個類的意思。
Android文檔中對Instrumentation類的描述:
/**
* Base class for implementing application instrumentation code. When running
* with instrumentation turned on, this class will be instantiated for you
* before any of the application code, allowing you to monitor all of the
*
interaction the system has with the application. An Instrumentation
*
implementation is described to the system through an AndroidManifest.xml's
* <instrumentation> tag.
*/
大意是:Instrumentation類會在應用的任何代碼執行前被實列化,用來監控系統與應用的交互。可在以應用的AndroidManifest.xml中<instrumentation>標籤來註冊一個Instrumentation的實現。
Java是面向對象的編程語言,每一個類都是一現實世界的一類對象的特徵描述,所以粗略地過一下Instrumentation.java代碼實現,先在大腦裏對它有一個整體的印象,然後在對該類的成員變量細看一下,可以知道這個類的規模,最後瀏覽一遍所有的方法,就可以大致這個類可能的特徵和行爲。
Instrumentation類沒繼承任何父類,也沒實現任何接口,這樣也比較好理解。
Instrumentation另一個重要作用是提供Android組件單元測試。
三、java.lang.instrument.Instrumentation
利用 Java 代碼,即 java.lang.instrument 做動態 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能從本地代碼中解放出來,使之可以用 Java 代碼的方式解決問題。使用 Instrumentation,開發者可以構建一個獨立於應用程序的代理程序(Agent),用來監測和協助運行在
JVM 上的程序,甚至能夠替換和修改某些類的定義。有了這樣的功能,開發者就可以實現更爲靈活的運行時虛擬機監控和 Java 類操作了,這樣的特性實際上提供了一種虛擬機級別支持的 AOP 實現方式,使得開發者無需對 JDK 做任何升級和改動,就可以實現某些 AOP 的功能了。
在 Java SE 6 裏面,instrumentation 包被賦予了更強大的功能:啓動後的 instrument、本地代碼(native code)instrument,以及動態改變 classpath 等等。這些改變,意味着 Java 具有了更強的動態控制、解釋能力,它使得 Java
語言變得更加靈活多變。
在 Java SE6 裏面,最大的改變使運行時的 Instrumentation 成爲可能。在 Java SE 5 中,Instrument 要求在運行前利用命令行參數或者系統參數來設置代理類,在實際的運行之中,虛擬機在初始化之時(在絕大多數的 Java 類庫被載入之前),instrumentation
的設置已經啓動,並在虛擬機中設置了回調函數,檢測特定類的加載情況,並完成實際工作。但是在實際的很多的情況下,我們沒有辦法在虛擬機啓動之時就爲其設定代理,這樣實際上限制了 instrument 的應用。而 Java SE 6 的新特性改變了這種情況,通過 Java Tool API 中的 attach 方式,我們可以很方便地在運行過程中動態地設置加載代理類,以達到 instrumentation 的目的。
另外,對 native 的 Instrumentation 也是 Java SE 6 的一個嶄新的功能,這使以前無法完成的功能 —— 對 native 接口的 instrumentation 可以在 Java SE 6 中,通過一個或者一系列的 prefix 添加而得以完成。
最後,Java SE 6 裏的 Instrumentation 也增加了動態添加 class path 的功能。所有這些新的功能,都使得 instrument 包的功能更加豐富,從而使 Java 語言本身更加強大。
Instrumentation 的最大作用,就是類定義動態改變和操作。在 Java SE 5 及其後續版本當中,開發者可以在一個普通 Java 程序(帶有 main 函數的 Java 類)運行時,通過 –
javaagent
參數指定一個特定的 jar 文件(包含 Instrumentation 代理)來啓動 Instrumentation 的代理程序。
四、源碼解析
1. Activity.java
1.1 成員mInstrumentation初始化
Activity類有一個私有Instrumentation成員mInstrumentation, 它只在Activity的attach()方法被賦值初始化。
// set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
private Instrumentation mInstrumentation;
......
【ActivityThread】[performLaunchActivity()]
↓
【Activity】[attach()]
↓
mInstrumentation = instr;
前面分析過從一個Activity子類A通過startActivity()方法啓動另一個Activity, 最後就是走到了ActivityThread的performLaunchActivity()方法,在這裏通過ClassLoader找到要啓動的Activity子類B,然後調用Activity子類B的attach()方法給Activity子類B賦以mInstrumentation。
1.2 startActivityForResult() Activity有幾個類似的啓動另一個Activity的方法startActivityForResult()一類方法,都是通過Instrumentation的execStartActivity()方法,並返回結果:
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity();
【Activity】[startActivity()]
↓
【Activity】[startActivityForResult()]
↓
【Instrumentation】[execStartActivity()]
......
從Activity的啓動流程看,這個函數執行比較早的,這裏的mInstrumentation要與上面的區分開來,這裏是已啓動的Activity子類A中的,
它已被初始化,而後面經attach後初始化的是Activity子類B的mInstrumentation。
1.3 performStart(), performRestart(),
performResume(), performStop() Activity的這四個方法會去調用 mInstrumentation的 callActivityOnStart(),
callActivityOnRestart(), callActivityOnResume(), callActivityOnStop(), 最終Activity的這四個方法會在ActivityThread對應的performXXXActivity()方法中被調用。
【ActivityThread】[performLaunchActivity()]
↓
【Activity】[performStart()]
↓
【Instrumentation】[callActivityOnStart()]
......
此處mInstrumentation是被啓動的Activity子類B經attach後成員變量。
2. ActivityThread.java
2.1 成員mInstrumentation初始化 ActivityThread類成員mInstrumentation,
它初始化的地方有三個:
(1) attach(boolean system), 此處system爲true, 表示創建的是SystemServer進程時,構造一個空的Instrumentation進行賦值,
並初始化SystemContext.
【SystemServer】[main()]
↓
【SystemServer】[run()]
↓
【SystemServer】[createSystemContext()]
↓
【ActivityThread】[systemMain()]
↓
【ActivityThread】[attach(true)]
......
(2) handleBindApplication(), [data.instrumentationName != null] 組件顯示調用startInstrumentation()方法才走到這裏。此時會通過ClassLoader的loadClass()找到該Class,
並實例化賦值給mInstrumentation, 並通過init()進行初始化。(此處要看是否有標籤<instrumentation>)
......
【ActivityManagerService】[startProcessLocked()]
↓
【Process】[start("android.app.ActivityThread", ...)]
↓
【ActivityThread】[main()]
↓
【ActivityThread】[attach(false)]
↓
【ActivityManagerService】[attachApplication()]
↓
【ActivityManagerService】[attachApplicationLocked()]
↓
【ActivityThread.ApplicationThread】[bindApplication()]
↓
【ActivityThread】[handleBindApplication()]
這裏再跟蹤哪裏給data.instrumentationName賦值,instrumentationName由ActivityThread. ApplicationThread的bindApplication()方法傳入,它在ActivityManagerService的attachApplicationLocked()方法中被調用,該方法傳入參數爲app.instrumentationClass,app爲ProcessRecord對象,其內部沒有給成員instrumentationClass
賦值的地方,故只在外部直接賦值,經搜索在ActivityManagerService的startInstrumentation()方法,最終可回溯到ContextImpl的startInstrumentation()方法,而我們知道ContextImpl就是ContextWraper的實際成員mBase, startInstrumentation()最終是在四大組件中在代碼裏顯示調用的,例如:
MainActivity.this.startInstrumentation( new ComponentName("com.settings.test", "android.test.InstrumentationTestRunner"), null,
null);
<instrumentation android:targetPackage="com.android.settings"
android:name="android.test.InstrumentationTestRunner" />
(3) handleBindApplication(),
[data.instrumentationName爲null] 構造APP唯一的Instrumentation.(所有應用第一次創建會走到這裏)
由(2)中的流程分析,一個應用進程在第一次啓動時會創建一個ActivityThread, 最終會在handleBindApplication()創建一個空的Instrumentation賦給ActivityThread的成員變量mInstrumentation,
後續每一個Activity在啓動時經過attach()方法,都會把該mInstrumentation傳入Activity賦給Activity.mInstrumentation,
也就是同一個應用進程內,所有Activity共用同一個Instrumentation。
2.2 handleBindApplication() 創建APP的ActivityThread,
Application對象。用到Instrumentation的newApplication(), callApplicationOnCreate()。
這個方法是ActivityThread創建時調用的,從前面我們知道當前app共用的一個Instrumentation也是在這裏創建。緊接着就是最重要部分該app的Application創建:
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
這裏data.info是一個LoadedApk對象,它是對應一個apk文件所有信息的,後面研究。這裏看看LoadedApk.makeApplication(boolean, Instrumentation)方法:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
......
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
initializeJavaContextClassLoader();
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
......
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
}
}
首先,通過mActivityThread.mInstrumentation.newApplication()來創建一個Application實例,過程也是通過本地的ClassLoader對象loadClass()方法找到對應Class, 再newInstance()。如果傳入的Instrumentation不爲空,就通過它的callApplicationOnCreate()方法調用當前app的Application的onCreate()方法,這裏傳入的是Instrumentation爲null, 在handleBindApplication()中會顯示調用mInstrumentation的callApplicationOnCreate()。這樣當前app的Application就準備好了,並在LoadedApk中會保存到mApplication。注意LoadedApk.makeApplication()第一句如果mApplication不爲null,
就會直接返回mApplication。這樣經過第一次創建,後面要newApplication()就直接返回已創建的,所以一個app只有一個Application對象。
2.3 performLaunchActivity()
startActivity()最後執行的地方。創建要啓動的Activity, 並調用Activity.attach()方法傳入Instrumentation及Application。用到Instrumentation的newActivity(), callActivityOnCreate().
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
......
} catch (Exception e) {
}
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.voiceInteractor);
......
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
2.4 handleReceiver() sendBroadcast()最後執行的地方。創建BroadcastReceiver對象,也是通過ClassLoader找到對應的BroadcastReceiver的Class並newInstance(), 然後調用receiver.onReceive(). 這裏也會調用到 LoadedApk.makeApplication(boolean, Instrumentation)方法,如果當前APP的Application對象還沒有創建,會通過 mActivityThread.mInstrumentation.newApplication()來創建一個Application實例。
private void handleReceiver(ReceiverData data) {
BroadcastReceiver receiver;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
......
}
try {
Application app = packageInfo.makeApplication(false, mInstrumentation);
ContextImpl context = (ContextImpl)app.getBaseContext();
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(), data.intent);
} catch (Exception e) {
......
}
}
......[第一次創建ActivityThread時]
【ActivityManagerService】[attachApplication()]
【ActivityManagerService】[attachApplicationLocked()]
↓
【ActivityManagerService】[sendPendingBroadcastsLocked()]
【BroadcastQueue】[sendPendingBroadcastsLocked()]
↓
【BroadcastQueue】[processCurBroadcastLocked()]----
↓
【ActivityThread.ApplicationThread】[scheduleReceiver()]
↓
【ActivityThread】[handleReceiver()]
從四大組件中發送一個廣播:
【contextImpl】[sendBroadcast()]
↓
【ActivityManagerService】[broadcastIntent()]
↓
【ActivityManagerService】[broadcastIntentLocked()]
↓
【BroadcastQueue】[scheduleBroadcastsLocked()]
↓
【BroadcastQueue】[processNextBroadcast()](很多地方會調用此函數)
↓
【BroadcastQueue】[processCurBroadcastLocked()]----
↓
【ActivityThread.ApplicationThread】[scheduleReceiver()]
↓
【ActivityThread】[handleReceiver()]
2.5 handleCreateService() startService()最後執行的地方。
......[第一次創建ActivityThread時]
【ActivityManagerService】[attachApplication()]
【ActivityManagerService】[attachApplicationLocked()]
【ActiveServices】[attachApplicationLocked()]
↓
【ActiveServices】[realStartServiceLocked()]----
↓
【ActivityThread.ApplicationThread】[scheduleCreateService()]
↓
【ActivityThread】[handleCreateService()]
[從四大組件中啓動一個Service]
【contextImpl】[startService()]
【contextImpl】[startServiceCommon()]
【ActivityManagerService】[startService()]
【ActiveServices】[startServiceLocked()]
【ActiveServices】[startServiceInnerLocked()]
【ActiveServices】[bringUpServiceLocked()]
【ActiveServices】[realStartServiceLocked()]----
【ActivityThread.ApplicationThread】[scheduleCreateService()]
【ActivityThread】[handleCreateService()]
2.6 installProvider() Context.getContentResolver().query()最後執行的地方。
【ContentResolver】[query()][insert()][delete()][update()]
【ContextImpl.ApplicationContentResolver】[acquireProvider()]
【ActivityThread】[acquireProvider()]
【ActivityManagerService】[getContentProvider()]
【ActivityManagerService】[getContentProviderImpl()]
【ActivityThread.ApplicationThread】[scheduleInstallProvider()]
【ActivityThread】[handleInstallProvider()]
【ActivityThread】[installContentProviders()]
【ActivityThread】[installProvider()]
五、總結
Instrumentation只在Activity和ActivityThread中有實例。一個APP啓動時會創建一個ActivityThread,
會在ActivityThread的handleBindApplication()創建一個空的Instrumentation對象並保存在ActivityThread的成員變量mInstrumentation, 後續每一個Activity在啓動時經過Activity的attach()方法,都會把ActivityThread的mInstrumentation賦給Activity的成員mInstrumentation,
也就是同一個應用進程內,所有Activity共用ActivityThread中的同一個Instrumentation。每一個APP的Application對像也是在handleBindApplication()中經由Instrumentation的newApplication()方法創建,且只有一個。
1. 每一個應用進程中只有唯一的ActivityThread, (ActivityThread中,成員【private static ActivityThread sCurrentActivityThread】,
方法【public static ActivityThread currentActivityThread()】)
2. 每一個應用進程中只有唯一的Application, (ActivityThread中,成員【Application mInitialApplication】,
方法【public Application getApplication()】)
3. 每一個應用進程中只有唯一的Instrumentation, (ActivityThread中,成員【Instrumentation mInstrumentation】, 方法【public Instrumentation getInstrumentation()】)
4. 四大組件第一次啓動時都會通過LoadedApk中的getClassLoader()方法,創建當前apk的PathClassLoader對象,後續每次要啓組新的組件都會通過該ClassLoader來得到組件實際的Class。
進程中某類的實例唯一性判斷:
(1) 一個靜態單例模式的類。
(2) 只被new或Class.newInstance()一次的成員;
(3) Java賦值"="的按值傳遞特性,而定義的實例名稱實際是指向一個地址,所以不論進行多少次的"="賦值,只要沒有new操作,各變量名實際都是指向同一個實例。
Activity啓動流程 :
【Activity】[startActivity()]
【Activity】[startActivityForResult()]
【Instrumentation】[execStartActivity()]
【ActivityManagerProxy】[startActivity()]
【ActivityManagerNative】[onTransact()]
【ActivityManagerService】[startActivity()]
【ActivityManagerService】[startActivityAsUser()].
【ActivityStackSupervisor】[startActivityMayWait()]
【ActivityStackSupervisor】[startActivityLocked()]
【ActivityStackSupervisor】[startActivityUncheckedLocked()]
【ActivityStack】[startActivityLocked()]
【ActivityStackSupervisor】[resumeTopActivitiesLocked()]
【ActivityStack】[resumeTopActivityLocked()]
【ActivityStack】[resumeTopActivityInnerLocked()]
【ActivityStackSupervisor】[startSpecificActivityLocked()]
--->這裏如果是Activity第一次啓動,會走到【ActivityManagerService】[startProcessLocked()]
創建進程。
【ActivityStackSupervisor】[realStartActivityLocked()]
【ActivityThread.ApplicationThread】[scheduleLaunchActivity()]
【ActivityThread】[handleLaunchActivity()]
【ActivityThread】[performLaunchActivity()]
【Instrumentation】[newActivity()]
【Instrumentation】[callActivityOnCreate()]
【Activity】[OnCreate()]
參考: