OC对象底层原理

313 阅读2分钟

一、runtime是什么?

用C、C++和汇编实现的一套API 给OC增加的运行时功能

二、alloc 和 init

+ (id)alloc {
    return _objc_rootAlloc(self);
}

汇编小知识:

bl --- 跳转

ret --- return

register read ----- 读取寄存器中的数据

x 对象内存地址 ----- 查看该对象数据

runtime小知识:

objec_msgSend(id 消息接收者 , sel ) ----- 任何方法调用的底层就是发送消息

sel ----- 方法编号 ,最终的底层是个name

IMP ---- 函数实现的指针

通过sel找到imp

id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
    if (slowpath(checkNil && !cls)) return nil;

#if __OBJC2__
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        // No alloc/allocWithZone implementation. Go straight to the allocator.
        // fixme store hasCustomAWZ in the non-meta class and 
        // add it to canAllocFast's summary
        if (fastpath(cls->canAllocFast())) {
            // No ctors, raw isa, etc. Go straight to the metal.
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
          	//**********↓↓↓↓↓↓↓↓↓↓↓↓↓**************
          	//**********↓↓↓↓↓↓↓↓↓↓↓↓↓**************
            id obj = class_createInstance(cls, 0);// 这再看不到我也没办法了
          	//**********↑↑↑↑↑↑↑↑↑↑↑↑**************
          	//**********↑↑↑↑↑↑↑↑↑↑↑↑**************
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif

    // No shortcuts available.
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}
id 
class_createInstance(Class cls, size_t extraBytes)
{
    return _class_createInstanceFromZone(cls, extraBytes, nil);// 且听下回分解
}

总结:

  • alloc 通过类创建实例对象
  • init 直接返回原来的对象,为了设计模式搞的设计
static __attribute__((always_inline)) 
id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                              bool cxxConstruct = true, 
                              size_t *outAllocatedSize = nil)
{
    if (!cls) return nil;

    assert(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();

    size_t size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (!zone  &&  fast) {
        obj = (id)calloc(1, size);
        if (!obj) return nil;
        obj->initInstanceIsa(cls, hasCxxDtor);
    } 
    else {
        if (zone) {
            obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
        } else {
            obj = (id)calloc(1, size);
        }
        if (!obj) return nil;

        // Use raw pointer isa on the assumption that they might be 
        // doing something weird with the zone or RR.
        obj->initIsa(cls);
    }

    if (cxxConstruct && hasCxxCtor) {
        obj = _objc_constructOrFree(obj, cls);
    }

    return obj;
}

字节对齐:

假如要以8对齐则 7 -> 8 、 10 -> 16 、 23 -> 24等

- (int)func(int x)
{
  return (x+7)>>3<<3;
}
- (int)func(int x)
{
  return (x+15)>>4<<4; // 以16对齐
}

以下三行为个人总结,若有错误,将来会修改:

对象中的属性或变量不够8位补够8位,但多个变量大小加一起不大于8则放在一起

isa 占8位,系统每8位读一次

但假如对象所有占用不到16的倍数,系统会开辟空间到16的倍数,原因如下:

#define SHIFT_NANO_QUANTUM      4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) // 16

static MALLOC_INLINE size_t
segregated_size_to_fit(nanozone_t *nanozone, size_t size,size_t *pKey)
{
  size_t k,slot_bytes;
  
  if (0 == size)
  {
    size = NANO_REGIME_QUANTA_SIZE;
  }
  // 16位对齐
  k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM;
  slot_bytes = k << SHIFT_NANO_QUANTUM;
  *pKey = k - 1;
  return slot_bytes;
}

alloc流程:

  1. alloc
  2. _objc_rootAlloc
  3. callAlloc
  4. class_createInstance
  5. _class_createInstanceFromZone
    • cls -> instanceSize // 算出属性大小
    • calloc // 得出系统分配的内存
    • obj -> initInstanceIsa // 实例化isa

三、OC对象的本质

是个结构体 objc_object