FBMemoryProfiler是Facebook开源的一款用于分析iOS内存使用和检测循环引用的工具库,可以让你在应用程序内运行循环应用检测。底层主要由FBAllocationTracker和FBRetainCycleDetector两块来实现功能。
FBAllocationTracker
通过在main.m中添加
[[FBAllocationTrackerManager sharedManager] startTrackingAllocations];
-->FB::AllocationTracker::beginTracking
--> replaceSelectorWithSelector([NSObject class],
@selector(alloc),
@selector(fb_newAlloc),
FBClassMethod);
replaceSelectorWithSelector([NSObject class],
sel_registerName("dealloc"),
@selector(fb_newDealloc),
FBInstanceMethod);
就开启了内存检测,主要是通过替换对象的+alloc 和 -delloc 方法,替换后
alloc-->fb_newAlloc是IMP-->
fb_originalAlloc-->alloc的IMP
所以[nsobject alloc]-->fb_newAlloc的IMP-->.....
FBRetainCycleDetector
对于通过objc_setAssociatedObject添加的对象,FBRetainCycleDetector也是可以检测的,这里就需要使用fishbook
来进行c函数的hook,fishhook是一个非常简单的库,它能动态替换运行在IOS模拟器或设备上Mach-o文件的符号表。是facebook的一个开源工具.
官网的一张图很好的解释了fishhook的原理:
dyld链接2种符号,lazy和non-lazy,fishhook可以重新链接/替换本地符号。如图所示,DATA区有两个section和动态符号链接相关:nl_symbol_ptr 、la_symbol_ptr。nl_symbol_ptr为一个指针数组,直接对应non-lazy绑定数据。__la_symbol_ptr也是一个指针数组,通过dyld_stub_binder辅助链接。的section头提供符号表的偏移量。图示中,1061是间接符号表的偏移量,*(偏移量+间接符号地址)=16343,即符号表偏移量。符号表中每一个结构都是一个nlist结构体,其中包含字符表偏移量。通过字符表偏移量最终确定函数指针。fishhook就是对间接符号表的偏移量动的手脚,提供一个假的nlist结构体,从而达到hook的目的。
具体的源码想要看懂,还是需要对mach_o文件结构有比较深入的理解的。使用过程还是如下
|
|
enableGenerations
开始追踪类的实例对象,就像instruments中的make generations一样,每个新创建的实例都会记录在对应的generations中
跟踪官方的demo(testObjectsRetainedBySomeObjectWillBeFetched),可以看到,通过object创建FBObjectiveCObject,然后调用allRetainedObjects–>_unfilteredRetainedObjects–>FBGetObjectStrongReferences–>FBGetStrongReferencesForClass
同时也包括[super allRetainedObjects]获取associations的强引用对象,最后通过如下代码生成FBObjectiveCGraphElement,就可以进行循环引用的搜索了。
|
|
其他代码学习
判断一个对象实例的iVar的类型
|
|
日常我们写一个property时,系统会默认给我们生成一个对应的_property的ivar,如果property前面添加了_,或者__呢,经试验系统还是会默认在这些前面继续加_的
那如何区分那些是weak,那些是strong呢,这里就需要对Class的 Ivar Layout有一定的了解
|
|
所以FBRetainCycleDetector中是通过取
const uint8_t *fullLayout = class_getIvarLayout(aCls);
来获取强引用类型的。