load方法研究

本文详细介绍了iOS中load方法的原理与应用,包括load的调用时机、底层实现过程,以及load方法的相关问题,如调用顺序和与initialize方法的区别。通过分析runtime源码,解析了load方法从查找、保存到调用的整个流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

load函数应该知道的事情
一、load介绍

类和分类的load方法是类或者分类被加载到runtime时被调用,并且只调用一次。类和分类的load方法都会调用。而“类或者分类被加载到runtime时”时动态链接阶段,此时main函数还未执行。

load 方法的运行时间过早,所以这里可能不是一个理想的环境,因为某些类可能需要在在其它类之前加载,但是这是我们无法保证的。

但是,framework以及动态库是先加载的,所有库加载完成之后,才会执行运行时的load方法,所以在load方法中调用 framework 中的方法都是安全的。

二、load底层实现

看756版本的runtime源码,可以看到load_images洪处理了load相关逻辑,下面我们仔细研读一下源码

/***********************************************************************
* load_images
* Process +load in the given images which are being mapped in by dyld.
*
* Locking: write-locks runtimeLock and loadMethodLock
**********************************************************************/
extern bool hasLoadMethods(const headerType *mhdr);
extern void prepare_load_methods(const headerType *mhdr);

void
load_images(const char *path __unused, const struct mach_header *mh)
{
    // Return without taking locks if there are no +load methods here.
    //1、判断镜像中是否有load方法,没有load方法,返回
    if (!hasLoadMethods((const headerType *)mh)) return;

		//加一个递归锁
    recursive_mutex_locker_t lock(loadMethodLock);

    // Discover load methods
    //2、查找所有的load方法
    {
        mutex_locker_t lock2(runtimeLock);
        //准备load方法
        prepare_load_methods((const headerType *)mh);
    }

    // Call +load methods (without runtimeLock - re-entrant)
    //3、调用所有的load方法
    call_load_methods();
}

通过上面的源码,我们可以总结load_images处理所有的load方法的过程:

先判断镜像中是否load方法(通过hasLoadMethods方法来实现)

  • 如果有,查找所有的load方法(prepare_load_methods实现),并且调用这些load方法(通过call_load_methods实现)
  • 如果没有,直接返回
第一阶段:查找所有的类和分类的load方法

1、hasLoadMethods方法

// Quick scan for +load methods that doesn't take a lock.
//快速查找load方法
bool hasLoadMethods(const headerType *mhdr)
{
    size_t count;
    if (_getObjc2NonlazyClassList(mhdr, &count)  &&  count > 0) return true;
    if (_getObjc2NonlazyCategoryList(mhdr, &count)  &&  count > 0) return true;
    return false;
}

hasLoadMethods方法通过_getObjc2NonlazyClassList() 和 _getObjc2NonlazyCategoryList()来查找类或者分类中是否有load方法,只有任何一个有load方法,说明需要处理load方法。

2、相关方法

我们了解到hasLoadMethods通过_getObjc2NonlazyClassList() 和 _getObjc2NonlazyCategoryList()来查找类或者分类是否有load方法,下面我们看看这两个方法的实现

//__objc_nlclslist表示类的load方法列表,__objc_nlcatlist表示分类的load方法列表
//      function name                 content type     section name    
GETSECT(_getObjc2NonlazyClassList,    classref_t,      "__objc_nlclslist");
GETSECT(_getObjc2NonlazyCategoryList, category_t *,    "__objc_nlcatlist");

#define GETSECT(name, type, sectname)                                   \
    type *name(const headerType *mhdr, size_t *outC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员的修养

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值