iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Swift类和对象的底层探索分析
  • 875
分享到

Swift类和对象的底层探索分析

2024-04-02 19:04:59 875人浏览 泡泡鱼
摘要

目录引言1. 对象1.1 上层代码中查找1.1.1 查找对象调用方法1.1.2 设置符号断点1.2 swift_allocObject1.3 swift_showAlloc1.4 查

引言

在上文已经了解了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 RefCounts<InlineRefCountBits> InlineRefCounts;
//是一个类,所以它的对象就是8个字节
class RefCounts {
  std::atomic<RefCountBits> 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<Inprocess>;

说明:

  • 上文可知对象结构体HeapObject包含有HeapMetadata结构体,对象通过它来查找对应的类信息
  • 点击进入HeapMetadata的定义,发现它是TargetHeapMetaData类型的别名
  • 并且接收了一个参数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
};

说明:

  • TargetHeapMetaData其本质是一个模板类型,其中定义了一些所需的数据结构
  • 这个结构体中没有属性,只有初始化方法
  • 初始化方法中传入了一个MetadataKind类型的参数,之后就可以返回TargetMetaData对象
  • 同时可以看到这里传入的kind也就是上面的inprocess了
  • 该初始化方法构造的对象需要通过该参数来确定

2.3. TargetMetaData

代码:

说明:

  • 在TargetMetaData中可以看到有一个Kind属性,这是在构建对象时传入的那个参数

查看MetadataKind

说明:

  • 可以看到它是uint32_t类型

类型

说明:

  • 进入MetadataKind定义,里面有一个#include "MetadataKind.def"
  • 点击进入,其中记录了所有类型的元数据

getClassObject方法:

const TargetClassMetadata<Runtime> *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<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;
    }
  }

说明:

  • 在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

代码:

template <typename Runtime>
struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
    ...
    //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类和对象的资料请关注编程网其它相关文章!

--结束END--

本文标题: Swift类和对象的底层探索分析

本文链接: https://www.lsjlt.com/news/166595.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Swift类和对象的底层探索分析
    目录引言1. 对象1.1 上层代码中查找1.1.1 查找对象调用方法1.1.2 设置符号断点1.2 swift_allocObject1.3 swift_showAlloc1.4 查...
    99+
    2022-11-13
  • Swift 指针底层探索分析
    目录概要1. 指针的认识1.1 指定类型指针1.2 未指定类型指针1.3 访问结构体实例对象2. 指针的常见绑定2.1 指针与内存空间的绑定(指向)(bindMemory)2.2 元...
    99+
    2022-11-13
  • Java基础之面向对象机制底层实现的示例分析
    这篇文章主要介绍Java基础之面向对象机制底层实现的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允...
    99+
    2023-06-14
  • Java类和对象的示例分析
    这篇文章给大家分享的是有关Java类和对象的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、什么是类类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实...
    99+
    2023-06-29
  • Python类和对象的示例分析
    这篇文章给大家分享的是有关Python类和对象的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、面向对象(一)程序员“面向对象”在现实世界中存在各种不同形态的事物,这些事物之间存在着各种各样的联系。在程...
    99+
    2023-06-29
  • Python面向对象中类和对象的示例分析
    这篇文章主要介绍了Python面向对象中类和对象的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是面向对象编程?我们是不是听过面向过程,拿来放在一起对比就比较好理...
    99+
    2023-06-22
  • C++类和对象深入探索之分文件编写点和圆的关系详解
    目录创建圆心类创建圆类判断点圆关系函数最终实现总结上一篇封装直达 创建圆心类 point.h #pragma once #include<iostream> using ...
    99+
    2022-11-13
  • Java中类和对象的示例分析
    这篇文章主要介绍了Java中类和对象的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。类可以看成是创建Java对象的模板1、类的定义public class&...
    99+
    2023-06-25
  • Java类和对象原理的示例分析
    小编给大家分享一下Java类和对象原理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!面向对象、面向过程什么是类?什么是对象?这是非常抽象的两个概念!!!!!!!!在说清楚类和对象的概念之前,给大家讲一下什么是面向...
    99+
    2023-06-29
  • Python面向对象和类的示例分析
    这篇文章主要为大家展示了“Python面向对象和类的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python面向对象和类的示例分析”这篇文章吧。一、两大编程思想二、类与对象简单举例:p...
    99+
    2023-06-26
  • C++深入探索类和对象之封装及class与struct的区别
    目录封装的意义访问权限class和struct的区别成员属性私有案例练习封装的意义 封装是C++三大面向对象之一 意义: 1、设计类的时候,属性和行为写在一起,表现事物 2、类在设计...
    99+
    2022-11-13
  • Java类和对象初始化过程的示例分析
    这篇文章主要介绍了Java类和对象初始化过程的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。  问题引入  近日我在调试一个枚举类型的解析器程序,该解析器是将数据库内...
    99+
    2023-06-03
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作