Objective-C-load

本文探讨了Objective-C中+load方法的调用顺序,包括函数调用规则、方法调用栈分析以及在Mac OS X下的实现细节。通过调试和分析dyld动态链接器,揭示了类、子类和分类中+load方法的执行流程,重点解析了类初始化、Category关联、load方法调度和执行的过程。
摘要由CSDN通过智能技术生成

你过去可能和笔者一样听说过,对于 load 方法的调用顺序有三条规则:

  1. main 函数之前由Objectvie-C的runtime调用
  2. 父类先于子类调用
  3. 类先于分类调用

首先写点代码测试一下上面的3条规则:


@implementation ALin
+ (void) load {
    NSLog(@"Alin ===== load");
}
@end

@implementation ALin (hi)
+ (void)load {
    NSLog(@"ALin+hi === load");
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"main");
    return 0;
    }
}

在main.n函数中仅仅是打印了一个main,没有调用任何的ALin这个类的任何+load,但是还是执行了ALin类实现的和ALin+hi分类中的+load.验证上面的三条规则确实没错.

![有帮助的截图]({ { site.url }}/assets/postsImages/load_ALin.png)

可是load 方法是究竟如何被调用的,+ load 方法为什么会有这种调用顺序呢?这些问题值得考究,首先来通过 load 方法的调用栈,分析一下它到底是如何被调用的。

因为 ObjC 的 runtime 只能在 Mac OS 下才能编译,所以文章中的代码都是在 Mac OS,也就是 x86_64 架构下运行的,你可以在objc-runtimeclone 整个仓库来进行调试。

在+ load中添加一个断点

![有帮助的截图]({ { site.url }}/assets/postsImages/load_stop_0.jpg)

左侧的调用栈很清楚的看到哪些方法被调用了:

0  +[ALin load]
1  call_class_loads()
2  call_load_methods
3  load_images
4  dyld::notifySingle(dyld_image_states, ImageLoader const*)
11 _dyld_start

dyld 是 the dynamic link editor 的缩写,它是苹果的动态链接器,又它来加载程序的可执行文件

每当有新的镜像加载之后,都会执行 3 load_images 方法进行回调,在进入load_images函数打下断点,查load_images看的调用栈。

![有帮助的截图]({ { site.url }}/assets/postsImages/load_load_images.jpg)

看了dyld_start之后进入了_objc_init:

void _objc_init(void)
{
    static bool initialized = false;
    if (initialized) return;
    initialized = true;
    environ_init();
    tls_init();
    static_init();
    lock_init();
    exception_init();
    _dyld_objc_notify_register(&map_images, load_images, unmap_image);
}

在这个函数调用_dyld_objc_notify_register注册了一个监听dyld加载image的函数,进入map_images:


map_images(unsigned count, const char * const paths[],
           const struct mach_header * const mhdrs[])
{
    rwlock_writer_t lock(runtimeLock);
    return map_images_nolock(count, paths, mhdrs);
}

随后发现最调用了_read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)去读取并检查所有的文件的内容,_read_images函数特别长,检查所有的header_info信息,针对不同的内容信息进行对应的处理,这里取一部分比较关心的内容:

Realize non-lazy classes

如果发现有+load方法的类的定义,或者static instances就会调用realizeClass(cls);对类进行初始化:

realizeClass(cls);是关注点

    // Realize non-lazy classes (for
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值