调用alloc方法底层流程
- 调用alloc方法
FCPerson *p = [FCPerson alloc]
. - 调用alloc方法时,llvm编译阶段会对alloc方法进行拦截,不会按正常流程调用
_objc_rootAlloc
,而是会先调用objc_alloc
,并对其进行特殊处理及标记,然后进入到callAlloc方法中 -
callAlloc
代码如下:
#if __OBJC2__
if (slowpath(checkNil && !cls)) return nil;
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
return _objc_rootAllocWithZone(cls, nil);
}
#endif
// No shortcuts available.
if (allocWithZone) {
return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
}
return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
第一次走到callAlloc时,不会走到return _objc_rootAllocWithZone(cls, nil);
,而是通过return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
对cls重新发送alloc消息。第二次调用alloc方法时,系统会判断对象已经经过特殊处理,可以走正常流程,则依次调用_objc_rootAlloc
, callAlloc
,最终走到OBJC2中的_objc_rootAllocWithZone
- 在
_objc_rootAllocWithZone
中会调用核心方法_class_createInstanceFromZone
:
- 通过
instanceSize
计算对象开辟的内存大小。对象的内存大小取决于对象拥有的成员变量和属性。当对象没有成员变量时,对象属性只有isa(继承于NSObject):Class isa OBJC_ISA_AVAILABILITY;
,Class isa
为结构体指针(struct objc_class *Class
),大小为8,通过内存储存条件if (size < 16) size = 16
决定了一个对象大小最小为16。
成员变量内存相加的结果为unalignedInstanceSize
, 根据内存对齐算法将unalignedInstanceSize 对齐:size_t size = alignedInstanceSize() + extraBytes;
,具体对齐算法请见iOS内存对齐算法解析。 - 然后使用isa将
FCPerson
与obj
进行绑定:
obj->initInstanceIsa(cls, hasCxxDtor);
isa绑定过程可见对象本质 & isa解析
-
整体流程图:
alloc流程
网友评论