一、HeapObject
-
之前在分析类的初始化流程中,我们可以看到
Swift源码中对象的初始化方法中最后返回了HeapObject对象。 -
我们查看
HeapObject的定义由此我们可以看到:
HeapObject有两个属性:metadata和refCounts,默认16字节。(OC的内存结构objc_object为8字节)metadata的类型HeapMetadata其实是TargetHeapMetadata。
二、TargetHeapMetadata
由此可以看出
TargetHeapMetadata继承自TargetMetadata,其次若该对象为纯Swift类,则入参为MetadataKind类型,若该对象与OC交互,则入参类型为OC中的isa。
三、TargetMetadata
-
进一步查看
TargetMetadata由此可以看出
TargetMetadata有StoredPointer类型的属性Kind;其次有个getKind方法,返回MetadataKind类型结果。 -
通过搜索
getKind方找到getTypeContextDescriptor由此可以看出该方法通过区分
getKind方法的返回值(MetadataKind)来返回不同的结果。当MetadataKind为Class时返回的是TargetClassMetadata。
static_cast<const TargetClassMetadata<Runtime> *>(this)是将当前对象强转为TargetClassMetadata。
-
进一步查看
TargetClassMetadata由此可以看出
TargetClassMetadata继承自TargetAnyClassMetadata -
进一步查看
TargetAnyClassMetadata从
TargetAnyClassMetadata数据结构中可以看到Superclass、CacheData、Data等属性(与OC类似)。 -
结合
TargetClassMetadata的其它属性(截取片段)分析推测出Swift类的数据结构
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,其内部有metadata和refCounts(8字节)。我们可以新增一个结构体,如下:
struct HeapObject {
var metadata: UnsafeRawPointer
var refCount1: UInt32
var refCount2: UInt32
}
refCounts可以分为2个4字节。
- 完整代码
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。
- 执行结果
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匹配,这与我们的推测是符合的。