isa指针

image.png
  • instance的isa指向class
    当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用
  • class的isa指向meta-class
    当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

class对象的superclass指针

image.png

当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

meta-class对象的superclass指针

image.png

当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

isa、superclass总结

  • instance的isa指向class
  • class的isa指向meta-class
  • meta-class的isa指向基类的meta-class
  • class的superclass指向父类的class
    如果没有父类,superclass指针为nil
  • meta-class的superclass指向父类的meta-class
    基类的meta-class的superclass指向基类的class
  • instance调用对象方法的轨迹
    isa找到class,方法不存在,就通过superclass找父类
  • class调用类方法的轨迹
    isa找meta-class,方法不存在,就通过superclass找父类
image.png

从64bit开始,isa需要进行一次位运算,才能计算出真实地址,如下图:


image.png
# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL

# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
image.png
(lldb) p/x person->isa
(Class) $5 = 0x001d8001000014d1 LQPerson//isa指针的地址
(lldb) p/x 0x001d8001000014d1 & 0x00007ffffffffff8
(long) $6 = 0x00000001000014d0 //class对象的地址

struct objc_class的结构

image.png

源码中的定义如下:

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;


struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() { 
        return bits.data();
    }
    void setData(class_rw_t *newData) {
        bits.setData(newData);
    }
......

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;

    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};

ro--readonly
rw--readwrite

struct lq_objc_class {
    Class isa;
    Class superclass;
};

LQPerson *person = [[LQPerson alloc] init];
Class personClass = [LQPerson class];
打印结果如下:
(lldb) p/x person->isa
(Class) $0 = 0x001d8001000014c9 LQPerson
(lldb) p/x personClass
(Class) $1 = 0x00000001000014c8 LQPerson
(lldb) p/x 0x001d8001000014c9 & 0x0000000ffffffff8
(long) $2 = 0x00000001000014c8

由此可见,实例对象的的isa确实指向class对象
也可以通过如下方式验证superClass

(lldb) p/x studentClass->superclass
(Class) $3 = 0x00000001000014c8 LQPerson

QA

  • 对象的isa指针指向哪里?

instance对象的isa指向class对象
class对象的isa指向meta-class对象
meta-class对象的isa指向基类的meta-class对象

  • OC的类信息存放在哪里?

对象方法、属性、成员变量、协议信息,存放在class对象中
类方法,存放在meta-class对象中
成员变量的具体值,存放在instance对象

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,999评论 0 9
  • 我们都知道OC对象分为三类,分别是:instance对象(实例对象)class对象(类对象)meta-class对...
    WolfMobile阅读 450评论 0 2
  • 最开始让我有疑问的是在使用类方法,在控制台下仍然发现Class对应的有地址,类没有初始化,为什么会有地址?这个地址...
    轰炸机上调鸡尾酒阅读 426评论 0 0
  • 在上一篇文章中我们浅谈了Objective-C对象在内存中的基本布局,在文章中的末尾部分我留下了两个疑问,什么是i...
    SuperMarioGG阅读 515评论 0 0
  • 每个人可能都会经历过一些 平庸的生活,我是一名96后,过往的20年中我真是尼玛太平庸了,而跑步给了我报复平庸的...
    大根日记阅读 748评论 0 3

友情链接更多精彩内容