FBAssociationManager is a tracker of object associations. For given object it can return all objects that are being retained by this object with objc_setAssociatedObject & retain policy.
FBRetainCycleDetector 在对关联对象进行追踪时,修改了底层处理关联对象的两个 C 函数,objc_setAssociatedObject 和 objc_removeAssociatedObjects。
FBAssociationManager
在 FBAssociationManager 的类方法 + hook 调用时,fishhook 会修改 objc_setAssociatedObject 和 objc_removeAssociatedObjects 方法:
+ (void)hook {
#if _INTERNAL_RCD_ENABLED
std::lock_guard《std::mutex》 l(*FB::AssociationManager::hookMutex);
rcd_rebind_symbols((struct rcd_rebinding[2]){
{
“objc_setAssociatedObject”,
(void *)FB::AssociationManager::fb_objc_setAssociatedObject,
(void **)&FB::AssociationManager::fb_orig_objc_setAssociatedObject
},
{
“objc_removeAssociatedObjects”,
(void *)FB::AssociationManager::fb_objc_removeAssociatedObjects,
(void **)&FB::AssociationManager::fb_orig_objc_removeAssociatedObjects
}}, 2);
FB::AssociationManager::hookTaken = true;
#endif //_INTERNAL_RCD_ENABLED
}
将它们的实现替换为 FB::AssociationManager:: fb_objc_setAssociatedObject 以及 FB::AssociationManager::fb_objc_removeAssociatedObjects 这两个 Cpp 静态方法。
上面的两个方法实现都位于 FB::AssociationManager 的命名空间中:
namespace FB { namespace AssociationManager {
using ObjectAssociationSet = std::unordered_set《void *》;
using AssociationMap = std::unordered_map《id, ObjectAssociationSet *》;
static auto _associationMap = new AssociationMap();
static auto _associationMutex = new std::mutex;
static std::mutex *hookMutex(new std::mutex);
static bool hookTaken = false;
。。.
}
命名空间中有两个用于存储关联对象的数据结构:
AssociationMap 用于存储从对象到 ObjectAssociationSet * 指针的映射
ObjectAssociationSet 用于存储某对象所有关联对象的集合
其中还有几个比较重要的成员变量:
_associationMap 就是 AssociationMap 的实例,是一个用于存储所有关联对象的数据结构
_associationMutex 用于在修改关联对象时加锁,防止出现线程竞争等问题,导致不可预知的情况发生
hookMutex 以及 hookTaken 都是在类方法 + hook 调用时使用的,用于保证 hook 只会执行一次并保证线程安全
用于追踪关联对象的静态方法 fb_objc_setAssociatedObject 只会追踪强引用:
static void fb_objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy) {
{
std::lock_guard《std::mutex》 l(*_associationMutex);
if (policy == OBJC_ASSOCIATION_RETAIN ||
policy == OBJC_ASSOCIATION_RETAIN_NONATOMIC) {
_threadUnsafeSetStrongAssociation(object, key, value);
} else {
// We can change the policy, we need to clear out the key
_threadUnsafeResetAssociationAtKey(object, key);
}
}
fb_orig_objc_setAssociatedObject(object, key, value, policy);
}
std::lock_guard《std::mutex》 l(*_associationMutex) 对 fb_objc_setAssociatedObject 过程加锁,防止死锁问题,不过 _associationMutex 会在作用域之外被释放。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !