iOS底层学习 - isa指针的底层实现

2020-09-14  本文已影响0人  w執念

本文的主要目的是理解isa指针相关的一些知识。

我们都知道oc对象的本质是一个结构体,想要更好的了解这个结构体,我们就需要用到apple主导编写的编译器clang,它是一个基于LLVM的C/C++/OC的编译器,主要是用于底层编译,将文件输出成c++文件,例如main.m 输出成main.cpp,其目的是为了更好的观察底层的一些结构 及 实现的逻辑,方便理解底层原理。
具体使用可参考:https://www.jianshu.com/p/9fc7776cce9b

在main中自定义一个类LGPerson,有一个属性name,通过终端,利用clang将main.m编译成 main.cpp


clang编译main.m.jpg

打开编译好的main.cpp,找到LGPerson的定义,发现LGPerson在底层会被编译成 struct 结构体。
LGPerson_IMPL中的第一个属性 其实就是 isa,是继承自NSObject,属于伪继承,伪继承的方式是直接将NSObject结构体定义为LGPerson中的第一个属性,意味着LGPerson 拥有 NSObject中的所有成员变量。
LGPerson中的第一个属性 NSObject_IVARS 等效于 NSObject中的 isa。

之前的博客中有画过一个alloc的底层执行流程分析图,我们来看看核心之一的initInstanceIsa方法,通过查看这个方法的源码实现,我们发现,isa指针的初始化,是通过isa_t这个类型来完成的,isa_t是使用联合体定义union,而在NSObject定义中isa的类型是Class,其根本原因是由于isa 对外反馈的是类信息,为了让开发人员更加清晰明确,需要在isa返回时做了一个类型的强制转换。

//initInstanceIsa
inline void 
objc_object::initInstanceIsa(Class cls, bool hasCxxDtor)
{
    ASSERT(!cls->instancesRequireRawIsa());
    ASSERT(hasCxxDtor == cls->hasCxxDtor());
    //初始化isa
    initIsa(cls, true, hasCxxDtor); 
}

//isa_t的定义
union isa_t { //联合体
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    //提供了cls 和 bits ,两者是互斥关系
    Class cls;
    uintptr_t bits;
#if defined(ISA_BITFIELD)
    struct {
        ISA_BITFIELD;  // defined in isa.h
    };
#endif
};

//isa返回时做的强制转换
inline Class 
objc_object::ISA() 
{
    ASSERT(!isTaggedPointer()); 
#if SUPPORT_INDEXED_ISA
    if (isa.nonpointer) {
        uintptr_t slot = isa.indexcls;
        return classForIndex((unsigned)slot);
    }
    return (Class)isa.bits;
#else
    return (Class)(isa.bits & ISA_MASK);//强制转换
#endif
}

联合体相比结构体,它也是由不同的数据类型组成,但其变量是互斥的,所有的成员共占一段内存。而且共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会将原来成员的值覆盖。
isa_t类型使用联合体的原因也是基于内存优化的考虑,这里的内存优化是指在isa指针中通过char + 位域(即二进制中每一位均可表示不同的信息)的原理实现。通常来说,isa指针占用的内存大小是8字节,即64位,已经足够存储很多的信息了,这样可以极大的节省内存,以提高性能。
从isa_t的定义中可以看出:

参考博客:https://www.jianshu.com/p/7fd6241a7124

上一篇 下一篇

猜你喜欢

热点阅读