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

2020-07-17  本文已影响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

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, 还有比较熟悉的几个属性,

在上面的截图中 (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中的数据

总结

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

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

上一篇 下一篇

猜你喜欢

热点阅读