美文网首页
02--对象本质04--类的结构

02--对象本质04--类的结构

作者: 修_远 | 来源:发表于2020-07-17 12:15 被阅读0次

[TOC]

  1. 怎么读到cache_t属性


    image

四个属性

在源码中关于类objc_class的结构体代码, 总共有200多行, 而我们最关注的只有上述四个属性

类结构源码
  1. // Class ISA;: 8字节

    • isa属性是继承与父类的属性, 所以是在属性的第一个位置, 表示isa指针
    • 指针占8个字节
  2. Class superclass;: 8字节

    • 除了isa属性之外, 父类指针就是第二个位置, 表示父类的isa指针
    • 指针占8个字节
  3. cache_t cache;: 16字节

    struct cache_t {
    struct bucket_t *_buckets;  // 8
    mask_t _mask;               // 4
    mask_t _occupied;           // 4
    

    我们可以先看看cache_t的结构, 根据内存对齐的规则, 可以计算出这个结构体的大小为 16字节

    • cache_t结构体
    • 16字节
  4. class_data_bits_t bits;: 所有的数据存储位置, 重点研究对象

探索四个属性

1. 准备类

@interface LGPerson : NSObject
{
NSString *_hobby;
}

@property (nonatomic, copy) NSString *lgName;

@end
  • 定义一个成员变量 _hobby
  • 定义一个属性 lgName
  • 我们知道编译器会自动生成一个 lgName 的getter和setter方法和一个带下划线的成员变量 _lgName

2. 查看 class_data_bits_t bits 属性

根据上面对objc_class的四个属性的分析, class_data_bits_t bits是在第四个属性的位置, 但不能仅根据属性字段的第四个位置的地址来输出它, 需要根据地址偏移来完成.
首地址偏移32位, 可以找到 bits 属性的地址,

p (class_data_bits_t *)(0x1000039a0+32)

class_data_bits_t

你肯定会有一个疑问, 为什么这里要强转成 class_data_bits_t * 而不是class_data_bits_t.

我们来看下面一行代码

class_rw_t *data() { 
    return bits.data();
}

data返回的是是一个指针类的数据, 我们可以猜测这里有一大坨的数据, 怎么读取这一坨数据, 自然就是我们的指针了, 可能有其他理论依据, 但这里作为一个探索分析就只能这么分析了。

【注意】在我们自己的iOS APP工程里面是无法分析的,原因是因为没有导入objc源码,所以无法找到 class_data_bits_t 类。

3. 查看 class_rw_t bits.data() 数据源

上面的截图中可以知道, 1表示 `bits`的指针, 那么就可以通过 `1` 来读取

p $1->data()

data

4. 分析 class_rw_t 结构

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;

    char *demangledName;

#if SUPPORT_INDEXED_ISA
    uint32_t index;
#endif
...

在这里看到了一个class_ro_t *ro, 不知道是什么, 但是既然是作为指针出现在这里, 一定是有它的意义的, 后面再做分析.
除了ro, 还有比较熟悉的几个属性,

  • method_array_t methods: 方法数组
  • property_array_t properties: 属性数组
  • protocol_array_t protocols: 协议数组

在上面的截图中 (class_rw_t *) $2 = 0x0000000101e68ef0, $2表示的是, class_rw_t *的指针, 那么可以尝试输出这个指针的值

p *$2

class_rw_t

5. 同样的方式分析ro

找到 ro 的指针
p $3.ro
打印 ro 的信息
p *$4

ro

6. 探索LGPerson中的数据

  • 成员变量 ivar

    找到 ivars 的指针
    $4->ivars
    打印 ivars 的信息
    p *$6

    ivar_list_t

    ivar_list_t中有个count = 2, 而我们知道我们定义的成员变量个数刚好为2,这里只输出了第一个, 所以下面要输出全部的成员变量.

    p $7.get(1)

    ivars
  • 方法 method
    同样的操作, 找到了编译器为我们自动生成的getter和setter方法


    method
  • 属性 properties
    同样的操作, 找到了lgName存在的地方


    properties

总结

这篇文章记录的是怎么探索类的结构,我们常用的数据都是在哪里、怎么存储的,没有对加载时机做分析(也即什么时候加载到这些地方),后面会讲。

探索完类的结构之后,有一种豁然开朗的感觉,以前都是靠猜测来分析属性、方法等存在哪里,现在能从内存中取出来,相当于是打开了潘多拉魔盒。

相关文章

  • 02--对象本质04--类的结构

    [TOC] 怎么读到cache_t属性image 四个属性 在源码中关于类objc_class的结构体代码, 总共...

  • iOS底层 -- Runtime之Class底层结构

    一、Class结构 类、元类对象的本质结构都是struct objc_class 类对象和元类对象的结构其实非常相...

  • OC中类的本质

    OC中的对象的本质 对象本身是一个含有isa指针的结构体,isa指针指向对象所属的类类的本质:类本质也是一个结构体...

  • iOS OC对象创建本质

    OC的类本质是一个结构体通过对main.m转换main.cpp可以看出,类对象的本质就是一个结构体。 对象创建本质...

  • iOS原理探索05 -- 类方法&经典面试题分析

    类方法的归属问题 我们在iOS原理探索04--类结构的分析中知道 类的实例方法和类的属性都存在bits中,我们发现...

  • Runtime

    1. 对象的本质:数据结构: 2. 对象,类对象和元类对象. 思考:如果我们调用类方法,没有对应的实现,但是有同名...

  • D面向对象

    ###内存管理 类:对象的模板,是对象的数据结构定义 对象:利用类作为模板创建的个体实例,本质是数据。 引用:是对...

  • 给字符串取别名(为了让代码更好看)

    最近项目有个需求是:01--居民身份证;02--军官证;03--护照;04--机动车驾驶证;05--港澳通行证;0...

  • runtime - iOS类对象、实例对象、元类对象

    理解类与对象的本质对于掌握一门语言是至关重要的,本文将从结构类型的角度探讨OC的类对象、实例对象、元类对象(Met...

  • Swift学习-进阶02

    swift对象本质,一个swift的对象默认占用16字节大小,在内存中的结构: swift类结构: 属性 存储属性...

网友评论

      本文标题:02--对象本质04--类的结构

      本文链接:https://www.haomeiwen.com/subject/uhhghktx.html