作者简介

刘徐兵(Alvin Liu),云智慧/开发经理。曾在高德、当当有多年大型App开发教训,在云智慧从事APM SDK研发工作5+年。对App开发和性能优化有深刻的钻研和实际。

iOS利用数据采集的根底 Objective-C Runtime

1、音讯转发

Objective-C语言扩大了C语言,扩大的外围在于引入了Runtime库,使Objective-C语言领有了面向对象和动静运行时的个性。而动静运行时机制的外围和体现是音讯转发机制。

Objective-C语言领有动静运行时的机制,办法的执行是在运行阶段决定的而不是在编译阶段决定的。而办法执行的本质是向对象发送了一个音讯,官网API为

objc_msgSend(void /* id self, SEL op, ... */ )

objc_msgSend有2个罕用参数:id self 和 SEL op,用于标识对象和办法,即向某个对象发送了某个音讯。因而Objective-C的[instance method]调用会被编译器转换成C语言API objc_msgSend的调用。

以下音讯转发机制原理图从官网文档翻译而来:

音讯转发机制示例图

如上图所示,Objective-C的音讯转发流程中,在以后对象办法列表中找不到办法的实现时,运行时环境会顺次进行三个阶段的查找

第一阶段

对象在收到无奈解决的音讯时,首先调用所属类的下列类办法。

+(BOOL)resolveInstanceMethod:(SEL)sel{     //默认返回NO     return NO;} +(BOOL)resolveClassMethod:(SEL)sel{     //默认返回NO     return NO;}

如果在其中找到了办法的实现,则进行音讯解决;否则就进入第二阶段。

第二阶段

在以后类里找不到该办法的实现时,运行时零碎尝试更换调用的对象,会调用如下办法

-(id)forwardingTargetForSelector:(SEL)aSelector{}

如果在该办法中还找不到办法的实现,就进入第三阶段。

第三阶段

到这里是最初一个阶段,通过创立NSInvocation实例,将与未解决的音讯无关的细节封装起来,运行时零碎调用的接口为

-(void)forwardInvocation:(NSInvocation *)anInvocation{}

该办法会沿着类的继承链始终往上调用,直至在NSObject的该办法中抛出doesNotRecognizeSelector:异样。

2、函数指针

SEL是Objective-C语言的办法选择器,也就是selector的指针。再往底层去,每个办法SEL还对应着一个IMP函数指针,指向办法实现的首地址。官网API为:

typedef id (*IMP)(id, SEL, ...); 

有了它就能够间接执行IMP指向的函数(办法)了。

以上介绍了实践根底,上面介绍下基于Objective-C语言动静运行时的办法拦挡(Hook)操作。

Hook原理

Hook步骤

  1. 应用Category个性往类中增加用于拦挡的办法SEL
  2. 应用零碎runtime的接口(Swizzle)替换办法实现体(IMP)

Hook应用示例图

如图所示,开发者调用原有办法时,会转发到拦挡的办法里,因替换了原办法与拦挡办法的入口地址(IMP),在拦挡办法执行完结时能调回原办法,对原有业务没有影响。

Hook回调函数

难点:不是类的实例形式,不能用Category个性。

优化前: 全工程扫描,再拦挡。

毛病:只能在主线程中操作,扫描文件数和耗费的工夫与App的规模大小成正比。

回调函数拦挡优化

步骤:

  1. 针对要应用protocol的零碎类应用Category个性增加拦挡办法
  2. 拦挡设置delegate的setter办法,获取到delegate的实例
  3. 针对获取到的delegate实例再进行回调办法拦挡

优化后

1、提早拦挡:在办法被调用时才被拦挡而且只拦挡一次

2、SDK的启动操作跟App的业务和规模无关,对App的影响降到最低

解体解码实际

目标: 理解iOS解体解码原理

解体解码步骤

  1. 虚拟内存偏移量:145624->0x238d8->0x00000001000238d8
  2. 应用dwarfdump命令,将dSYM文件解析成可读文件

dwarfdum-e--debug-info 蕴含全副类和办法的代码和地址映射信息->信息文件

dwarfdum-e--debug-line 蕴含全副类的代码行号和地址映射信息->行号文件

  1. 在信息文件中查找偏移量所在的类和办法,失去解体的类和对应的办法
  2. 在行号文件中查找偏移量所在的行号,失去具体的解体行号

虚拟内存偏移量:

0x00000001000238d8

dSYM文件解析命令

  1. symbolicatecrash->全文本解析
  2. atos(mac)/atosl(linux)->单行解析

H5页面监控原理

以上介绍了零碎原生接口的数据采集原理,上面介绍下H5页面数据采集实现原理。

H5页面数据采集通过主动往H5页面注入JS代码实现。流程如下图所示

H5页面注入JS代码示意图

如上图所示,在UIWebView时代,通过NSURLProtocol协定簇的接口,拦挡到加载页面数据的接口,获取到H5数据块,检测数据块中的<head>标签,将JS代码注入到<head>中。这样JS代码就和H5页面代码一起加载、工作,可能采集到H5页面的相干信息。JS代码采集到信息后,通过iframe的形式触发UIWebView的回调将信息发送给原生SDK端存储、上报。

在WKWebView时代,因为WKWebView是独自的过程,在App里从零碎的网络协议簇无奈获取到WKWebView的数据,可通过拦挡WKWebView的回调函数去执行JS代码,能起到与UIWebView同样的数据采集成果。这里不再赘述。

PS:JS代码的工作原理是另一个技术畛域的领域,不在这里赘述。

写在最初

近年来,在AIOps畛域疾速倒退的背景下,IT工具、平台能力、解决方案、AI场景及可用数据集的迫切需要在各行业爆发。基于此,云智慧在2021年8月公布了AIOps社区, 旨在树起一面开源旗号,为各行业客户、用户、研究者和开发者们构建沉闷的用户及开发者社区,独特奉献及解决行业难题、促成该畛域技术倒退。

社区先后 开源 了数据可视化编排平台-FlyFish、运维治理平台 OMP 、云服务治理平台-摩尔平台、 Hours 算法等产品。

我的项目介绍:https://www.cloudwise.ai/flyF...

Github地址: https://github.com/CloudWise-...

Gitee地址: https://gitee.com/CloudWise/f...

请您通过下方链接理解咱们,增加小助手微信(xiaoyuerwie),备注:飞鱼。申请加入开发者交换群,可与业内大咖进行1V1交换!

也可分割咱们理解云智慧AIOps资讯,理解云智慧开源社区其余我的项目开源状况!