Swift(四)-对象的内存结构

842 阅读2分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

通过上一篇文章针对类的SIL文件的分析,我们已经了解了在Swift中对象进行内存分配的流程,接下来我们继续分析对象的内存结构;

Swift对象内存结构

HeapObject

Swift对象的内存结构是HeapObject(OC对象的内存结构为objc_object);其定义如下: image.png 其有两个属性:

  • Metadata
  • RefCounts:默认占用16字节大小;根据HeapObject的定义可知:
    • metadata占用8字节;
    • SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS占用8字节;
    • refCounts:是一个64位的位域信息;

Swift对象默认占用16字节,OC对象默认占用8字节;

那么HeapMetadata的内存结构是什么样子呢?

HeapMetadata

Swift源码中我们可以找到: image.png HeapMetadataTargetHeapMetadata这个类型的别名定义。

TargetHeapMetadata

其定义如下: image.png TargetHeapMetadata继承自TargetMetadata; ​

从其定义可以分析得知:如果该类是一个纯Swift类,那么其类型为MetadataKind,如果该类需要与objc交互,那么它就是我们OC中常见的isa

MetadataKind

MetadataKind定义如下: image.png 该类中没有相关信息,我们需要分析TargetHeapMetadata的父类TargetMetadata

TargetMetadata

该类定义代码有些长,未截取!从代码可以分析出:TargetMetadataKindStoredPointer类型。在该类中有函数getTypeContextDescriptor: image.png 在该函数中通过getKind返回的类型来区分当前的类型;而TargetClassMetadata就是所有类型元类最终基类; 如果是Class,那么将会把当前指针this通过static_cast强转为TargetClassMetadata类型;

TargetClassMetadata

TargetClassMetadata继承自TargetAnyClassMetadata

TargetAnyClassMetadata

TargetAnyClassMetadata的数据结构中我们发现,其结构中含有SuperclassCacheData[2]Data等属性,这与OC类的结构很相似;

总结

从而我们可以分析得到如下的数据结构:

struct Metadata{
    var kind: Int
    var superClass: Any.Type
    var cacheData: (Int, Int)
    var data: Int
    var classFlags: Int32
    var instanceAddressPoint: UInt32
    var instanceSize: UInt32
    var instanceAlignmentMask: UInt16
    var reserved: UInt16
    var classSize: UInt32
    var classAddressPoint: UInt32
    var typeDescriptor: UnsafeMutableRawPointer
    var iVarDestroyer: UnsafeRawPointer
}

该数据结构,极有可能就是我们Swift类的数据结构; ​

接下来我们验证此数据结构,我们将此结构体绑定为类的指针类型; 我们前面已经分析得到Swift的内存结构是HeapObject,其内部含有metadata64位的refCounts,那么我们来创建一个结构体如下: image.png

64位的refCounts分为两个32位的refCountHeapObject就是我们当前对象的实例结构;

那么变量t存储的内存地址应该就是指向结构体HeapObject,那么我们就可以将t指针重新绑定位HeapObject结构体类型: image.png 可以看到metadatarefCount1中有值,refCount1为何为3后续再讲解; ​

同样的,我们可以将metadata还原成Metadata的结构体类型,代码如下: image.png