首先定義一個Swift類辛块,打斷點,進入到匯編模式笨蚁;
會看callq一個__allocating_init()函數(shù)览濒,沿著此函數(shù)開始Swift類的探索
設(shè)置符號斷點:__allocating_init,發(fā)現(xiàn)其調(diào)用了swift_allocObject;
進入到swift_allocObject,其屬于libswiftCore.dylib,然后進入到底層源碼
_swift_allocObject源碼可知,主要有以下幾個部分
1井仰、通過swift_slowAlloc開辟空間并進行內(nèi)存對齊
2了罪、通過new (object) HeapObject(metadata); 初始化一個實例對象
3娃圆、返回對象是HeapObject,所以當前對象的內(nèi)存結(jié)構(gòu)就是HeapObject的內(nèi)存結(jié)構(gòu)
進入到swift_slowAlloc源碼谦炬,主要就是通過malloc在堆內(nèi)存中開辟size大小的內(nèi)存空間稚机,并返回內(nèi)存地址(主要是用于存儲實例變量)
HeapObject是一個結(jié)構(gòu)體仿贬;
初始化HeapObject需要兩個參數(shù)metadata (HeapMetadata),refCounts(InlineRefCounts)
其中:
HeapMetadata是一個結(jié)構(gòu)體占8個字節(jié);
refCounts是引用計數(shù),類型是:InlineRefCounts姨拥,而InlineRefCounts是RefCounts的一個別名绅喉,占8個字節(jié)
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
分析至此可知:
1、對于對象來說叫乌,其本質(zhì)是一個HeapObject結(jié)構(gòu)體柴罐,默認16字節(jié)內(nèi)存大小
2、Swift內(nèi)存分配流程是:__allocating_init --> swift_allocObject?-->??_swift_allocObject_ --> swift_slowAlloc --> malloc
HeapMetadata類型分析:
HeapMetadata是TargetHeapMetadata的別名憨奸,接收一個參數(shù)InProcess
進入TargetHeapMetadata類源碼革屠,發(fā)現(xiàn)其繼承自TargetMetadata:
TargetHeapMetadata本質(zhì)上是一個模版類型,其中定義了一些所需的數(shù)據(jù)結(jié)構(gòu)排宰;
其構(gòu)造方法TargetHeapMetadata傳入一個MetadataKind類型的參數(shù)(通過前面分析可知似芝,此處的kind就是InProcess)
在TargetMetadata源碼中可知,有Kind屬性板甘,kind的類型就是之前傳入的Inprocess.
通過TargetHeapMetadata和TargetMetadata可知kind的類型是MetadataKind;
進入其源碼發(fā)現(xiàn)類型其實就是uint32_t党瓮,主要作用就是區(qū)分是哪種類型的元數(shù)據(jù)
進入到MetadataKind.def中,其中記錄了所有類型的元數(shù)據(jù)盐类;
明確了kind的作用寞奸,回到TargetMetadata中,找到getClassObject方法在跳,在該方法中去匹配kind枪萄,返回值是TargetClassMetadata
通過上圖中紅色框中內(nèi)容可知,如果是swift原生則直接將this強轉(zhuǎn)為ClassMetadata
using ClassMetadata = TargetClassMetadata<InProcess>;
進入到TaretClassMetadata中猫妙,其繼承自:TargetAnyClassMetadata瓷翻,看其源碼有如下屬性,這些屬性也是類結(jié)構(gòu)的部分
TargetClassMetadata中的屬性:
ClassFlags Flags; ? ?//swift特有的標志
uint32_t InstanceAddressPoint; ? ?//實例獨享內(nèi)存首地址
uint32_t InstanceSize; ? ?//實例對象內(nèi)存大小
uint16_t InstanceAlignMask; ? ?//實例對象內(nèi)存對齊方式
uint16_t Reserved; ? ?//運行時保留字段
uint32_t ClassSize; ? ?//類的內(nèi)存大小
uint32_t ClassAddressPoint; ? ?//類的內(nèi)存首地址
進入到TargetAnyClassMetadata割坠,發(fā)現(xiàn)其繼承自TargetHeapMetadata
通過以上源碼分析可知:
當metadata的kind為Class時逻悠,繼承關(guān)系如下:
1、TargetClassMetadata --->TargetAnyClassMetadata-->TargetHeapMatadata-->TargetMetadata
2韭脊、當前類返回的實際類型是TargetClassMetadata,而TargetMatedata中只有一個屬性Kind童谒;TargetAnyClassClassMetadata有4個屬性:Kind、Superclass沪羔、CacheData饥伊、Data
3象浑、當前class存放的屬性由 TargetClassMetadata屬性+TargetAnyClassMetadata屬性+TargetMetaData屬性構(gòu)成
即:
struct swift_class_t: NSObject {
? ? void *kind;????????//相當于oc中的iSA
? ? void *superClass;
? ? void *cacheData;
????void *data;
? ?ClassFlags Flags; ? ?//swift特有的標志
? ?uint32_t InstanceAddressPoint; ? ?//實例獨享內(nèi)存首地址
? ?uint32_t InstanceSize; ? ?//實例對象內(nèi)存大小
? ?uint16_t InstanceAlignMask; ? ?//實例對象內(nèi)存對齊方式
? ?uint16_t Reserved; ? ?//運行時保留字段
? ?uint32_t ClassSize; ? ?//類的內(nèi)存大小
? ?uint32_t ClassAddressPoint; ? ?//類的內(nèi)存首地址
? ? void *description;
? ? ...
}
Swift與OC的對比
1、實例對象:
OC中的實例對象本質(zhì)是結(jié)構(gòu)體琅豆,通過底層的objc_object模版創(chuàng)建愉豺,類是繼承自objc_class
Swift中的實例對象本質(zhì)是結(jié)構(gòu)體,類型是HeapObject茫因,比OC多了一個refCounts
2蚪拦、方法列表:
OC中的方法列表存儲在objc_class結(jié)構(gòu)體bi(class_rw_t)的methodList中
Swift中的方法存儲在metadata元數(shù)據(jù)中
3、引用計數(shù):
OC中的ARC是存儲在全局的sidetable中
Swift中的引用計數(shù)是對象內(nèi)部由一個refCounts屬性存儲