目录
引言
在上文已经了解了sil,接下来主要通过swift源码和sil剖析底层。本文主要通过底层源码探索类和对象在底层的结构
主要内容:
- 对象
- 类
1. 对象
通过源码中探索swift对象创建过程以及最终得到的对象结构。
1.1 上层代码中查找
通过符号断点调试来查找底层调用方法
源码:
class wystudent { var age: int = 18 var name: string = "wy" } var stu = wystudent();
1.1.1 查找对象调用方法
通过断点查看发现是通过__allocating_init()方法实现对象的创建
添加断点
查看调用方法
1.1.2 设置符号断点
符号断点:
查看:
说明:
- 在上面sil的认识中已经知道了对象是通过__allocating_init()来创建的,在此处打断点查看
- 在__allocating_init()方法中可以看到会调用swift_allocobject()方法
- 因此接下来就需要在源码中查看该方法
- __allocating_init()方法中做了两件事
- 调用swift_allocobject创建对象
- 调用init()初始化对象,这个init方法是类默认提供的,也是默认调用的
1.2 swift_allocobject
说明:
- 通过swift_slowalloc分配内存,并进行内存字节对齐,传入开辟的内存空间大小和对齐位数
- 通过heapobject方法构造一个heapobject对象,并且绑定到object上
- 因此此时的object就是一个heapobject对象
- 函数的返回值是heapobject类型,所以当前对象的内存结构就是heapobject的内存结构
1.3 swift_showalloc
// apple malloc is always 16-byte aligned. # define malloc_align_mask 15
说明:
- 通过swift_slowalloc用来分配内存空间
- 这里会通过对齐位数来判断使用哪种方法来分配空间
- 最小的对齐位数是16字节,如果传入的位数小于16字节,那么就是用16字节对齐,也就是使用malloc方法
- 如果大于16字节位数,那么使用alignedalloc方法
1.4 查看heapobject结构体
结构体
refcounts查看:
typedef refcountsinlinerefcounts; //是一个类,所以它的对象就是8个字节 class refcounts { std::atomic refcounts;//引用计数 ... }
说明:
- 结构体内包含一个成员,metadata
- heapobject()初始化器,会初始化metadata和refcounts,因此对象中会有这两种属性
- 其中metadata类型是heapmetadata,是一个指针类型,占8字节,其实它就是类信息
- refcounts是引用计数,也占有8个字节
- refcounts的类型是inlinerefcounts
- 而inlinerefcounts是一个类refcounts的别名
- refcounts是一个类,所以refcounts占8个字节
1.5 对象内存大小计算
说明:
- metadata占8个字节
- refcounts占8个字节
- 再加上age的8个字节
- name占8个字节
- 所以总共是40个字节
1.6 总结
实例对象的底层结构是heapobject结构体
默认16字节内存大小,metadata 8字节 refcounts 8字节
metadata是类信息结构,下面会分析
refcounts是引用计数,后面也会详细分析
swift中对象的内存分配流程是:
__ allocating_init --> swift_allocobject_ --> _swift_allocobject --> swift_slowalloc --> malloc
2. 类
对象在底层中的结构是heapobject结构体,其第一个属性为metadata,因此从这个属性出发来查看类的结构
2.1 查找heapmetadata
代码:
using heapmetadata = targetheapmetadata;
说明:
- 上文可知对象结构体heapobject包含有heapmetadata结构体,对象通过它来查找对应的类信息
- 点击进入heapmetadata的定义,发现它是targetheapmetadata类型的别名
- 并且接收了一个参数inprocess
2.2. targetheapmetadata
代码:
//模板类型 templatestruct targetheapmetadata : targetmetadata { using headertype = targetheapmetadataheader ; targetheapmetadata() = default; //初始化方法 constexpr targetheapmetadata(metadatakind kind) : targetmetadata (kind) {} #if swift_objc_interop constexpr targetheapmetadata(targetanyclassmetadata *isa) : targetmetadata (isa) {} #endif };
说明:
- targetheapmetadata其本质是一个模板类型,其中定义了一些所需的数据结构
- 这个结构体中没有属性,只有初始化方法
- 初始化方法中传入了一个metadatakind类型的参数,之后就可以返回targetmetadata对象
- 同时可以看到这里传入的kind也就是上面的inprocess了
- 该初始化方法构造的对象需要通过该参数来确定
2.3. targetmetadata
代码:
说明:
- 在targetmetadata中可以看到有一个kind属性,这是在构建对象时传入的那个参数
查看metadatakind
说明:
- 可以看到它是uint32_t类型
类型
说明:
- 进入metadatakind定义,里面有一个#include "metadatakind.def"
- 点击进入,其中记录了所有类型的元数据
getclassobject方法:
const targetclassmetadata*getclassobject() const; //******** 具体实现 ******** template<> inline const classmetadata * metadata::getclassobject() const { //匹配kind switch (getkind()) { //如果kind是class case metadatakind::class: { // native swift class metadata is also the class object. //将当前指针强转为classmetadata类型 return static_cast (this); } case metadatakind::objcclasswrapper: { // objective-c class objects are referenced by their swift metadata wrapper. auto wrapper = static_cast (this); return wrapper->class; } // other kinds of types don't have class objects. default: return nullptr; } }
说明:
- 在targetmetadata结构体定义中有一个方法getclassobject,它就可以用来获取类对象,也就是类
- 在方法中的核心逻辑是通过kind来判断当前是哪种类型,之后返回
- 这里我们需要的是类类型,因此判断为metadatakind::class,就会返回classmetadata类型
验证:
命令:
po metadata->getkind()
得到其kind是class
po metadata->getclassobject() x/8g 0x0000000110efdc70
这个地址中存储的是元数据信息!
说明:
- 传递进来的kind发现可以判断为类
- 通过方法调用最后得到的是一个类对象,也就是类
- 通过x/8g查看类信息,里面就是存储的元数据信息
注意:
- targetmetadata 和 targetclassmetadata 本质上是一样的
- 因为在内存结构中,可以直接进行指针的转换,所以可以说,我们认为的结构体,其实就是targetclassmetadata
2.4. targetclassmetadata
代码:
templatestruct targetclassmetadata : public targetanyclassmetadata { ... //swift特有的标志 classflags flags; //实力对象内存大小 uint32_t instancesize; //实例对象内存对齐方式 uint16_t instancealignmask; //运行时保留字段 uint16_t reserved; //类的内存大小 uint32_t classsize; //类的内存首地址 uint32_t classaddresspoint; ... }
说明:
- 包含了很多属性,这些都属于类结构信息
- 并且它继承自targetanyclassmetadata
2.5. targetanyclassmetadata
代码:
说明:
- targetanyclassmetadata是所有的类结构,不单单是给swift用的
- 继承自targetheapmetadata,这也证明类本身也是对象
- 提供有isa、superclass、cache、data,和oc的底层类结构完全一样
以上就是swift类和对象的底层探索分析的详细内容,更多关于swift类和对象的资料请关注其它相关文章!