欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Swift類和對(duì)象的底層探索分析

 更新時(shí)間:2022年09月06日 11:21:31   作者:文乙  
這篇文章主要為大家介紹了Swift類和對(duì)象的底層探索分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

在上文已經(jīng)了解了SIL,接下來(lái)主要通過(guò)Swift源碼和SIL剖析底層。本文主要通過(guò)底層源碼探索類和對(duì)象在底層的結(jié)構(gòu)

主要內(nèi)容:

  • 對(duì)象

1. 對(duì)象

通過(guò)源碼中探索Swift對(duì)象創(chuàng)建過(guò)程以及最終得到的對(duì)象結(jié)構(gòu)。

1.1 上層代碼中查找

通過(guò)符號(hào)斷點(diǎn)調(diào)試來(lái)查找底層調(diào)用方法

源碼:

class WYStudent {
    var age: Int = 18
    var name: String = "WY"
}
var stu = WYStudent();

1.1.1 查找對(duì)象調(diào)用方法

通過(guò)斷點(diǎn)查看發(fā)現(xiàn)是通過(guò)__allocating_init()方法實(shí)現(xiàn)對(duì)象的創(chuàng)建

添加斷點(diǎn)

查看調(diào)用方法

1.1.2 設(shè)置符號(hào)斷點(diǎn)

符號(hào)斷點(diǎn):

查看:

說(shuō)明:

  • 在上面SIL的認(rèn)識(shí)中已經(jīng)知道了對(duì)象是通過(guò)__allocating_init()來(lái)創(chuàng)建的,在此處打斷點(diǎn)查看
  • 在__allocating_init()方法中可以看到會(huì)調(diào)用swift_allocObject()方法
  • 因此接下來(lái)就需要在源碼中查看該方法
  • __allocating_init()方法中做了兩件事
    • 調(diào)用swift_allocObject創(chuàng)建對(duì)象
    • 調(diào)用init()初始化對(duì)象,這個(gè)init方法是類默認(rèn)提供的,也是默認(rèn)調(diào)用的

1.2 swift_allocObject

說(shuō)明:

  • 通過(guò)swift_slowAlloc分配內(nèi)存,并進(jìn)行內(nèi)存字節(jié)對(duì)齊,傳入開(kāi)辟的內(nèi)存空間大小和對(duì)齊位數(shù)
  • 通過(guò)HeapObject方法構(gòu)造一個(gè)HeapObject對(duì)象,并且綁定到object上
  • 因此此時(shí)的object就是一個(gè)heapObject對(duì)象
  • 函數(shù)的返回值是HeapObject類型,所以當(dāng)前對(duì)象的內(nèi)存結(jié)構(gòu)就是HeapObject的內(nèi)存結(jié)構(gòu)

1.3 swift_showAlloc

// Apple malloc is always 16-byte aligned.
#  define MALLOC_ALIGN_MASK 15

說(shuō)明:

  • 通過(guò)swift_slowAlloc用來(lái)分配內(nèi)存空間
  • 這里會(huì)通過(guò)對(duì)齊位數(shù)來(lái)判斷使用哪種方法來(lái)分配空間
  • 最小的對(duì)齊位數(shù)是16字節(jié),如果傳入的位數(shù)小于16字節(jié),那么就是用16字節(jié)對(duì)齊,也就是使用malloc方法
  • 如果大于16字節(jié)位數(shù),那么使用AlignedAlloc方法

1.4 查看HeapObject結(jié)構(gòu)體

結(jié)構(gòu)體

refCounts查看:

typedef RefCounts<InlineRefCountBits> InlineRefCounts;
//是一個(gè)類,所以它的對(duì)象就是8個(gè)字節(jié)
class RefCounts {
  std::atomic<RefCountBits> refCounts;//引用計(jì)數(shù)
  ...
}

說(shuō)明:

  • 結(jié)構(gòu)體內(nèi)包含一個(gè)成員,metadata
  • HeapObject()初始化器,會(huì)初始化metadata和refCounts,因此對(duì)象中會(huì)有這兩種屬性
  • 其中metadata類型是HeapMetadata,是一個(gè)指針類型,占8字節(jié),其實(shí)它就是類信息
  • refCounts是引用計(jì)數(shù),也占有8個(gè)字節(jié)
  • refCounts的類型是InlineRefCounts
  • 而InlineRefCounts是一個(gè)類RefCounts的別名
  • RefCounts是一個(gè)類,所以refCounts占8個(gè)字節(jié)

1.5 對(duì)象內(nèi)存大小計(jì)算

說(shuō)明:

  • metadata占8個(gè)字節(jié)
  • refCounts占8個(gè)字節(jié)
  • 再加上age的8個(gè)字節(jié)
  • name占8個(gè)字節(jié)
  • 所以總共是40個(gè)字節(jié)

1.6 總結(jié)

實(shí)例對(duì)象的底層結(jié)構(gòu)是HeapObject結(jié)構(gòu)體

默認(rèn)16字節(jié)內(nèi)存大小,metadata 8字節(jié) + refCounts 8字節(jié)

metadata是類信息結(jié)構(gòu),下面會(huì)分析

refCounts是引用計(jì)數(shù),后面也會(huì)詳細(xì)分析

Swift中對(duì)象的內(nèi)存分配流程是:

__ allocating_init --> swift_allocObject_ --> _swift_allocObject --> swift_slowAlloc --> malloc

2. 類

對(duì)象在底層中的結(jié)構(gòu)是HeapObject結(jié)構(gòu)體,其第一個(gè)屬性為metadata,因此從這個(gè)屬性出發(fā)來(lái)查看類的結(jié)構(gòu)

2.1 查找HeapMetadata

代碼:

using HeapMetadata = TargetHeapMetaData<Inprocess>;

說(shuō)明:

  • 上文可知對(duì)象結(jié)構(gòu)體HeapObject包含有HeapMetadata結(jié)構(gòu)體,對(duì)象通過(guò)它來(lái)查找對(duì)應(yīng)的類信息
  • 點(diǎn)擊進(jìn)入HeapMetadata的定義,發(fā)現(xiàn)它是TargetHeapMetaData類型的別名
  • 并且接收了一個(gè)參數(shù)Inprocess

2.2. TargetHeapMetaData

代碼:

//模板類型
template <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
  using HeaderType = TargetHeapMetadataHeader<Runtime>;
  TargetHeapMetadata() = default;
  //初始化方法
  constexpr TargetHeapMetadata(MetadataKind kind)
    : TargetMetadata<Runtime>(kind) {}
#if SWIFT_OBJC_INTEROP
  constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
    : TargetMetadata<Runtime>(isa) {}
#endif
};

說(shuō)明:

  • TargetHeapMetaData其本質(zhì)是一個(gè)模板類型,其中定義了一些所需的數(shù)據(jù)結(jié)構(gòu)
  • 這個(gè)結(jié)構(gòu)體中沒(méi)有屬性,只有初始化方法
  • 初始化方法中傳入了一個(gè)MetadataKind類型的參數(shù),之后就可以返回TargetMetaData對(duì)象
  • 同時(shí)可以看到這里傳入的kind也就是上面的inprocess了
  • 該初始化方法構(gòu)造的對(duì)象需要通過(guò)該參數(shù)來(lái)確定

2.3. TargetMetaData

代碼:

說(shuō)明:

  • 在TargetMetaData中可以看到有一個(gè)Kind屬性,這是在構(gòu)建對(duì)象時(shí)傳入的那個(gè)參數(shù)

查看MetadataKind

說(shuō)明:

  • 可以看到它是uint32_t類型

類型

說(shuō)明:

  • 進(jìn)入MetadataKind定義,里面有一個(gè)#include "MetadataKind.def"
  • 點(diǎn)擊進(jìn)入,其中記錄了所有類型的元數(shù)據(jù)

getClassObject方法:

const TargetClassMetadata<Runtime> *getClassObject() const;
//******** 具體實(shí)現(xiàn) ********
template<> inline const ClassMetadata *
  Metadata::getClassObject() const {
    //匹配kind
    switch (getKind()) {
      //如果kind是class
    case MetadataKind::Class: {
      // Native Swift class metadata is also the class object.
      //將當(dāng)前指針強(qiáng)轉(zhuǎn)為ClassMetadata類型
      return static_cast<const ClassMetadata *>(this);
    }
    case MetadataKind::ObjCClassWrapper: {
      // Objective-C class objects are referenced by their Swift metadata wrapper.
      auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
      return wrapper->Class;
    }
    // Other kinds of types don't have class objects.
    default:
      return nullptr;
    }
  }

說(shuō)明:

  • 在TargetMetaData結(jié)構(gòu)體定義中有一個(gè)方法getClassObject,它就可以用來(lái)獲取類對(duì)象,也就是類
  • 在方法中的核心邏輯是通過(guò)kind來(lái)判斷當(dāng)前是哪種類型,之后返回
  • 這里我們需要的是類類型,因此判斷為MetadataKind::Class,就會(huì)返回ClassMetadata類型

驗(yàn)證:

命令:

po metadata->getKind()

得到其kind是Class

po metadata->getClassObject() + x/8g 0x0000000110efdc70

這個(gè)地址中存儲(chǔ)的是元數(shù)據(jù)信息!

說(shuō)明:

  • 傳遞進(jìn)來(lái)的Kind發(fā)現(xiàn)可以判斷為類
  • 通過(guò)方法調(diào)用最后得到的是一個(gè)類對(duì)象,也就是類
  • 通過(guò)x/8g查看類信息,里面就是存儲(chǔ)的元數(shù)據(jù)信息

注意:

  • TargetMetadata 和 TargetClassMetadata 本質(zhì)上是一樣的
  • 因?yàn)樵趦?nèi)存結(jié)構(gòu)中,可以直接進(jìn)行指針的轉(zhuǎn)換,所以可以說(shuō),我們認(rèn)為的結(jié)構(gòu)體,其實(shí)就是TargetClassMetadata

2.4. TargetClassMetadata

代碼:

template <typename Runtime>
struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
    ...
    //swift特有的標(biāo)志
    ClassFlags Flags;
    //實(shí)力對(duì)象內(nèi)存大小
    uint32_t InstanceSize;
    //實(shí)例對(duì)象內(nèi)存對(duì)齊方式
    uint16_t InstanceAlignMask;
    //運(yùn)行時(shí)保留字段
    uint16_t Reserved;
    //類的內(nèi)存大小
    uint32_t ClassSize;
    //類的內(nèi)存首地址
    uint32_t ClassAddressPoint;
  ...
}

說(shuō)明:

  • 包含了很多屬性,這些都屬于類結(jié)構(gòu)信息
  • 并且它繼承自TargetAnyClassMetadata

2.5. TargetAnyClassMetadata

代碼:

說(shuō)明:

  • TargetAnyClassMetadata是所有的類結(jié)構(gòu),不單單是給Swift用的
  • 繼承自TargetHeapMetadata,這也證明類本身也是對(duì)象
  • 提供有isa、superclass、cache、data,和OC的底層類結(jié)構(gòu)完全一樣

以上就是Swift類和對(duì)象的底層探索分析的詳細(xì)內(nèi)容,更多關(guān)于Swift類和對(duì)象的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論