All Projects → lele8446 → CJMethodLog

lele8446 / CJMethodLog

Licence: MIT license
Objective-C 函数日志监听系统,可监听任意类,任意类的任意方法的调用日志。

Programming Languages

objective c
16641 projects - #2 most used programming language
Objective-C++
1391 projects

Projects that are alternatives of or similar to CJMethodLog

Anymethodlog
Log any method call of object in Objective-C
Stars: ✭ 361 (+1288.46%)
Mutual labels:  log, runtime
state inspector
State change & method call logger. A debugging tool for instance variables and method calls.
Stars: ✭ 24 (-7.69%)
Mutual labels:  hooks, log
Icmethoddigger
An easy way to print almost methods including private methods (supported arm64 architecture devices).
Stars: ✭ 103 (+296.15%)
Mutual labels:  log, runtime
Ddetours
Delphi Detours Library
Stars: ✭ 256 (+884.62%)
Mutual labels:  hooks, runtime
AppRun
AppDir runtime components
Stars: ✭ 19 (-26.92%)
Mutual labels:  hooks, runtime
Swifthook
A library to hook methods in Swift and Objective-C.
Stars: ✭ 93 (+257.69%)
Mutual labels:  hooks, runtime
GAlogger
Log R Events and R Usage to Google Analytics
Stars: ✭ 23 (-11.54%)
Mutual labels:  log
Elite-Log-Agent
Lightweight, non-intrusive data uploader for Elite Dangerous
Stars: ✭ 42 (+61.54%)
Mutual labels:  log
use-elapsed-time
React hook to measure elapsed time using requestAnimationFrame
Stars: ✭ 42 (+61.54%)
Mutual labels:  hooks
transition-hook
☄️ An extremely light-weight react transition animation hook which is simpler and easier to use than react-transition-group
Stars: ✭ 250 (+861.54%)
Mutual labels:  hooks
git-templates
Templates / Hooks for Your Git Repositories
Stars: ✭ 30 (+15.38%)
Mutual labels:  hooks
react-native-log-level
Multi level logger for React Native
Stars: ✭ 13 (-50%)
Mutual labels:  log
entangle
Global state management tool for react hooks inspired by RecoilJS and Jotai using proxies.
Stars: ✭ 26 (+0%)
Mutual labels:  hooks
react-hook-sticky
react hook sticky
Stars: ✭ 19 (-26.92%)
Mutual labels:  hooks
architectury-api
An intermediary api aimed at easing development of multiplatform mods.
Stars: ✭ 139 (+434.62%)
Mutual labels:  hooks
logt
🖥️ A colourful logger for the browser
Stars: ✭ 35 (+34.62%)
Mutual labels:  log
vscode-react-javascript-snippets
Extension for React/Javascript snippets with search supporting ES7+ and babel features
Stars: ✭ 782 (+2907.69%)
Mutual labels:  hooks
TailLog
实时日志(tail log)查看监控客户端工具
Stars: ✭ 79 (+203.85%)
Mutual labels:  log
aegis-host
This is the ÆGIS federated application host. Federated components are independently deployable, written by multiple teams in multiple languages, and loaded from multiple repos and network locations at runtime, yet capable of running together in a single process or as distributed components in the ÆGIS application fabric.
Stars: ✭ 197 (+657.69%)
Mutual labels:  runtime
twitch-chatlog
Fetch the chatlog to a twitch VOD from your command line.
Stars: ✭ 78 (+200%)
Mutual labels:  log

CJMethodLog

功能

Objective-C 函数日志监听系统。
CJMethodLog 对于 Objective-C 中的任意类、任意类的任意方法,均可监听其调用日志。

应用场景

  1. 还原用户操作对应的函数调用堆栈
  2. 分析各函数执行时的性能消耗情况
  3. 一些难以重现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;

forwardingClassMethod

基于runtime的消息转发机制实现,当一个方法进入消息转发会存在以下步骤:

  1. +resolveInstanceMethod: (或+resolveClassMethod:)。允许用户在此时为该Class动态添加实现。如果有实现,并返回YES,那么重新开始objc_msgSend流程。同时对象会响应这个选择器,一般是因为它已经调用过class_addMethod。如果仍没实现,继续下面的动作。

  2. -forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。

  3. -methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用-doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给-forwardInvocation:

  4. -forwardInvocation:方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。

  5. -doesNotRecognizeSelector: ,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。

forwardingClassMethod 运用了消息转发机制,在app启动的时候hook方法,具体流程如下:

  1. 根据class_copyMethodList遍历获取到指定类aClass的所有方法
  2. 获取当前方法originMethod的IMP,同时把originMethod的IMP替换为_objc_msgForward,使得调用该方法的时候自动触发消息转发机制
  3. 新增规定前缀开头的方法newMethodaClass类中,newMethod的IMP为第2步中获取到的IMP
  4. 重写当前类-forwardInvocation:方法的IMP为自定义的imp_implementationWithBlock,最后在自定义block里注入方法调用日志,同时使用NSInvocation调用第三步中新增的方法newMethod,从而还原当前方法本来的实现

不足,子类父类不能同时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运行的每一行代码说起

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].