Objective-C 函数日志监听系统。
CJMethodLog
对于 Objective-C 中的任意类、任意类的任意方法,均可监听其调用日志。
- 还原用户操作对应的函数调用堆栈
- 分析各函数执行时的性能消耗情况
- 一些难以重现bug(非crash)的分析
下图展示了hook TestViewController
类之后的函数调用情况
日志格式说明:
- <TestViewController> begin: -clickManagerTest:
-- <TestViewController> begin: +managerTest
-- <TestViewController> finish: +managerTest ; time=0.000110
- <TestViewController> finish: -clickManagerTest: ; time=0.000416
- 最开始的
-
表示函数调用层级; <TestViewController>
表示当前调用函数的类名;begin:
finish:
分别表示函数执行起始阶段(在设置了CJLogMethodTimer或者CJLogMethodReturnValue选项的时候出现);-clickManagerTest:
表示实例方法,+managerTest
表示类方法;time=0.000110
表示函数耗时- 之后会补充函数参数以及返回结果说明
在 main.m
文件中设置需要监听的类名配置,理论上任意时刻都可以重设监听配置,但不建议这么做!!因为每次重设监听配置都会修改监听类的methodLists中方法的IMP实现,另外 main.m
中配置可以确保所有hook类都生效,例如如果你hook的是 AppDelegate
类。
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "CJMethodLog.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
/*
* 利用消息转发,hook指定类的调用方法
*/
[CJMethodLog forwardingClasses:@[
@"TestViewController",
]
logOptions:CJLogDefault|CJLogMethodTimer
logEnabled:YES];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
获取日志数据使用+ (void)syncLogData:(SyncDataBlock)finishBlock
,你可以根据需要获取。比如这里在app启动的时候获取,判断当数据量大于10*1024的时候上传服务器并删除客户端数据。
- (void)applicationDidBecomeActive:(UIApplication *)application {
[CJMethodLog syncLogData:^void(NSData *logData) {
NSLog(@"CJMethodLog: logData = %@",@([logData length]));
if ([logData length] > 10*1024) {
// TODO: 上传到服务器等自定义处理
// 删除日志数据
[CJMethodLog clearLogData];
}
}];
}
CJMethodLog
调用方式如下:
+ (void)forwardingClasses:(NSArray <NSString *>*)classNameList logOptions:(CJLogOptions)options logEnabled:(BOOL)value;
基于runtime的消息转发机制实现,当一个方法进入消息转发会存在以下步骤:
|
forwardingClassMethod 运用了消息转发机制,在app启动的时候hook方法,具体流程如下:
|
不足,子类父类不能同时hook同名方法!!!
原因: 当hook的类存在继承关系时,由于对于父类、子类同名的方法都换成了相同的IMP即_objc_msgForward
,在执行父类方法时,虽然触发的是objc_msgSendSuper
,但获取到的IMP却是同一个,会形成死循环。而在Hook之前,objc_msgSendSuper
拿到的是super_imp
, objc_msgSend
拿到是imp
,从而不会有问题
- 解决
self
super
上下文调用的问题 - 欢迎各位大神
star
issue
,帮忙解决难题
CJMethodLog 使用 MIT 许可证,详情见 LICENSE 文件
CJMethodLog(一)Runtime原理:从监控还原APP运行的每一行代码说起
CJMethodLog 二:从监控还原APP运行的每一行代码说起