注:转载请注明来自Nemo,http://blog.csdn.net/nemo__


一、包名
         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()]
Activity】[onStart()]

......
此处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】[m ain()]
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);
<instrumentationandroid: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。用到InstrumentationnewActivity(),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.4handleReceiver()  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 ActivityThreadcurrentActivityThread())
2. 每一个应用进程中只有唯一的Application(ActivityThread中,成员【Application mInitialApplication】, 方法【public ApplicationgetApplication())
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()]


参考:
http://www.ibm.com/developerworks/cn/java/j-lo-jse61/index.html




【Android源码-AMS】(一)Instrumentation类解析相关推荐

  1. spring源码分析06-spring配置类解析

    什么是spring配置类? 类上有注解:@Configuration .@Component.@ComponentScan.@Import.@ImportResource 或者类中的任意方法有@Bea ...

  2. Android源码解析(一)动画篇-- Animator属性动画系统

    Android源码解析-动画篇 Android源码解析(一)动画篇-- Animator属性动画系统 Android源码解析(二)动画篇-- ObjectAnimator Android在3.0版本中 ...

  3. Android源码解析--AlertDialog及AlertDialog.Builder

    昨天晚上弄到很晚,简单的看了下Dialog的源码,说要分析下建造者模式,在dialog里面的应用其实是在AlertDialog中. 按照惯例,先看类说明: [java] view plaincopy ...

  4. 《Android源码设计模式解析与实战》读书笔记(十七)

    第十七章.中介者模式 中介者模式也称为调解者模式或调停者模式,是一种行为型模式. 1.定义 中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用.从而使它们可以松散耦合.当某些对象之 ...

  5. 《Android源码设计模式解析与实战》读书笔记(十)

    第十章.解释器模式 解释器模式是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式.但是它的使用场景确实很广泛,只是因为我们自己很少回去构造一个语言的文法,所以使用较少. 1.定义 ...

  6. 《Android源码设计模式解析与实战》读书笔记(十三)

    第十三章.备忘录模式 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,有点像是我们平常说的"后悔药". 1.定义 在不破坏封闭的前提下,捕获 ...

  7. 【Android源码】源码分析深度好文+精编内核解析分享

    阅读Android源码的好处有很多,比如:可以加深我们对系统的了解:可以参考牛人优雅的代码实现:可以从根本上找出一些bug的原因-我们应该庆幸Android是开源的,所有的功能都可以看到实现,所有的b ...

  8. Android核心服务解析篇(二)——Android源码结构分析

    版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 获得Android源码后,我们来分析源码结构.源码的全部工程分为如下三个部分. ①Core Project:核心工程部分,这是建 ...

  9. 《深入解析Android 虚拟机》——第1章,第1.3节编译Android源码

    本节书摘来自异步社区<深入解析Android 虚拟机>一书中的第1章,第1.3节编译Android源码,作者 钟世礼,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...

最新文章

  1. 全局性业务架构建模工作步骤
  2. 北航计算机学硕还是专硕,2018北航计算机专硕总分第一录取经验
  3. 关于IR21的自举电路
  4. hdu4685 最大匹配可能性
  5. Ubuntu 14.04 python3.6 安装
  6. STM32 进阶教程 6 -  汇编与C混合编程
  7. 使用dubbo后尽量不用要@Service可能引起冲突
  8. java 格式化时间计算
  9. 神经架构搜索(Neural Architecture Search,NAS)介绍
  10. 电脑java语言有什么用_Java语言是什么?_Java语言有什么优点
  11. 程序员:请不要对我的代码指手画脚!
  12. Android之ListView优化(使用Lrucache,图片滑动时使用默认图片,停止时加载)
  13. WebService—规范介绍和几种实现WebService的框架介绍
  14. 博文视点Open Party第8期
  15. python爆破脚本_snmp爆破(python脚本)
  16. 线性代数高频考题:判断含参数的线性方程组解的形式
  17. DeepFace: Closing the Gap to Human-Level Performance in Face Verification
  18. 微信公众平台开发入门
  19. Spring Destroying singletons ... root of factory hierarchy 问题【已解决】
  20. 以Java工程师为例,技术面试应该怎么准备?

热门文章

  1. 把wget玩出花来:获得几乎你想要的一切!包括Dropbox和google drive
  2. 软件测试基础笔记总结
  3. 机器人操作系统ROS(3)工作空间
  4. 木马防线:一切木马都是纸老虎(中)(转)
  5. HTTP协议与TCP协议简单理解--转自博客园--留着学习
  6. latex三线表格绘制
  7. python毕业设计选题推荐100例
  8. 青科大编程赛热身赛C题:火柴棒等式
  9. 弹出启动windows安全中心服务器,如何解决Win7系统无法启动Windows安全中心的问题?...
  10. 参与广州的第四届手机应用开发者大会感想