4. 类的数据结构

224 阅读3分钟

一、HeapObject

  1. 之前在分析类的初始化流程中,我们可以看到Swift源码中对象的初始化方法中最后返回了HeapObject对象。 07e7b8fd0f664810a8fae8259b614f4c.png

  2. 我们查看HeapObject的定义 1fc51e528e1401b50505c57228cdd4ed.png 由此我们可以看到:

  • HeapObject有两个属性:metadatarefCounts,默认16字节。(OC的内存结构objc_object为8字节)
  • metadata的类型HeapMetadata 其实是TargetHeapMetadata

二、TargetHeapMetadata

6db9fb9ed20bb8f81e1e07616327600b.png 由此可以看出TargetHeapMetadata继承自TargetMetadata,其次若该对象为纯Swift类,则入参为MetadataKind类型,若该对象与OC交互,则入参类型为OC中的isa

三、TargetMetadata

  1. 进一步查看TargetMetadata 663061c8bc03455e5be4c57ad1225991.png 由此可以看出TargetMetadataStoredPointer类型的属性Kind;其次有个getKind方法,返回MetadataKind类型结果。

  2. 通过搜索getKind方找到getTypeContextDescriptor d169cf210712f38cab76de09dfdba9d1.png 由此可以看出该方法通过区分getKind方法的返回值(MetadataKind)来返回不同的结果。当MetadataKindClass时返回的是TargetClassMetadata

static_cast<const TargetClassMetadata<Runtime> *>(this)是将当前对象强转为TargetClassMetadata

  1. 进一步查看TargetClassMetadata 1ed11e0c3446751af6c556f3560a041d.png 由此可以看出TargetClassMetadata继承自TargetAnyClassMetadata

  2. 进一步查看TargetAnyClassMetadata 4b1b96cea1895bb80ee82f22d296e460.pngTargetAnyClassMetadata数据结构中可以看到SuperclassCacheDataData等属性(与OC类似)。

  3. 结合TargetClassMetadata的其它属性(截取片段)分析推测出Swift类的数据结构 b7d00ced627bbacbca66422559bd3ff9.png

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类的数据结构。

四、验证

  1. 之前在分析类的初始化流程中我们得知Swift类的内存结构为HeapObject,其内部有metadatarefCounts(8字节)。我们可以新增一个结构体,如下:
struct HeapObject {
    var metadata: UnsafeRawPointer
    var refCount1: UInt32
    var refCount2: UInt32
}

refCounts可以分为2个4字节。

  1. 完整代码
import Foundation

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
}

struct HeapObject {
    var metadata: UnsafeRawPointer
    var refCount1: UInt32
    var refCount2: UInt32
}

class Teacher {
    var name = "Tom"
    var age = 3
}

let t = Teacher()

/// 获取实例对象指针
let point = Unmanaged.passUnretained(t as AnyObject).toOpaque()
/// 指针绑定为 HeapObject 类型
let objc = point.bindMemory(to: HeapObject.self, capacity: 1)
print(objc.pointee)

/// 将 HeapObject.metadata 指针绑定为 Metadata 类型
let metadata = objc.pointee.metadata.bindMemory(to: Metadata.self, capacity: MemoryLayout<Metadata>.stride)
print(metadata.pointee)

我们可以将Teacher实例指针绑定为结构体HeapObject,然后将HeapObject.metadata属性指针绑定到结构体Metadata

  1. 执行结果
HeapObject(metadata: 0x0000000100008230, refCount1: 2, refCount2: 0)
Metadata(kind: 4295000568, superClass: _TtCs12_SwiftObject, cacheData: (140734973522240, 206158430208), data: 4303066098, classFlags: 2, instanceAddressPoint: 0, instanceSize: 40, instanceAlignmentMask: 7, reserved: 0, classSize: 168, classAddressPoint: 16, typeDescriptor: 0x0000000100003ba0, iVarDestroyer: 0x0000000000000000)

由结果可以看出,Swift类的数据结构与Metadata匹配,这与我们的推测是符合的。