runtime 分类结构体_Objective-C RunTime 学习笔记 之 基础结构体

1、OC 运行期常用对象结构体

基本的结构体定义

typedef objc_class Class; /* 类 */

typedef objc_object *id; /* 各种类型,只要第一个字段为isa_t 即可,兼容Class */

1.2) isa_t 联合体定义

union isa_t  {

Class cls;

uintptr_t bits; /* unsigned long 无符号长整形,8个字节 */

#if SUPPORT_NONPOINTER_ISA

# if __arm64__

struct {

uintptr_t indexed      : 1;

uintptr_t has_assoc     : 1;

uintptr_t has_cxx_dtor   : 1;

uintptr_t shiftcls     : 33; // MACH_VM_MAX_ADDRESS 0x1000000000

uintptr_t magic       : 6;

uintptr_t weakly_referenced : 1;

uintptr_t deallocating   : 1;

uintptr_t has_sidetable_rc : 1;

uintptr_t extra_rc     : 19;

};

# elif __x86_64__

struct {

uintptr_t indexed      : 1;

uintptr_t has_assoc     : 1;

uintptr_t has_cxx_dtor   : 1;

uintptr_t shiftcls     : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000

uintptr_t magic       : 6;

uintptr_t weakly_referenced : 1;

uintptr_t deallocating   : 1;

uintptr_t has_sidetable_rc : 1;

uintptr_t extra_rc     : 8;

};

# else

#  error unknown architecture

# endif

#endif

};

当64位下,使用 extra_rc 来存储引用计数,如果超出则同时将extra_rc的一半移到SideTable中。

1.3) objc_object/objc_class 结构体定义

/* Foundation 对象 */

struct objc_object {

private:

isa_t isa; // 仅仅定义了isa的联合体

/* ... 省略各种方法 */

}

/* 类 */

struct objc_class : objc_object {

// Class ISA;

Class superclass;

cache_t cache;       // formerly cache pointer and vtable

class_data_bits_t bits;  // class_rw_t * plus custom rr/alloc flags

/* ...省略各种方法 */

}

可以看到无论是类还是对象,第一个字段为 isa_t ,在实例对象中指向类(存放实例变量内存布局、方法列表、属性列表、协议列表),而类则指向元类(类的方法列表、属性列表、协议列表)。class中有一个关键的结构体 class_data_bits_t

1.4) class_data_bits_t 结构体定义

struct class_data_bits_t {

// Values are the FAST_ flags above.

uintptr_t bits;

/* 不同的位域存储不同的FLAG 和 class_rw_t 结构体的指针 */

/* 省略各种方法 */

}

在bits字段中,除了指向一个运行期的结构体 class_rw_t, 还在低4位标注了一些标识

bits(低4位注明一些FAST flag(64 位)) 说明:

a) calloc与malloc 分配的内存,在64位下,返回的有效地址为,从低到高的位顺序位 5-44位为有效值,因此,高20位与低4位为无效字段,可以通过这些字段进行存储有效值。

#define FAST_DATA_MASK     0x00007ffffffffff8ULclass_rw_t  指针地址位掩码64位下, malloc/calloc 低5位到44位为有效地址空间)

b) 第一位如果为1(#define FAST_IS_SWIFT      (1UL<<0)) 意味着是swift class

c) 第二位如果为1(#define FAST_HAS_DEFAULT_RR   (1UL<<1)) 意味着有默认的实现 retain/release/autorelease/retainCount

d) 第三位如果为1(#define FAST_REQUIRES_RAW_ISA  (1UL<<2)) 意味着类的默认的实现 alloc/allocWithZone:

1.5) class_rw_t/class_ro_t 结构体定义

struct class_rw_t {

uint32_t flags;          /* 定义flag集合 */

uint32_t version;         /* 类的版本,貌似元类为7,普通类为0 */

const class_ro_t *ro;       /* 这个结构体存放的编译期实例变量的布局以及实例变量的size、方法列表、属性列表、协议列表 */

method_array_t methods;        /* 实例方法数组 */

property_array_t properties;   /* 实例属性数组 */

protocol_array_t protocols;    /* 协议数组 */

Class firstSubclass;

Class nextSiblingClass;

char *demangledName;          /* 类名 */

/* 省略各种方法 */

}

struct class_ro_t {

uint32_t flags;

uint32_t instanceStart;     /* 实例变量开始的偏移量 */

uint32_t instanceSize;     /* NSObject 类需要分配的字节数 */

#ifdef __LP64__

uint32_t reserved;

#endif

const uint8_t * ivarLayout;       /* 布局 */

const char * name;

method_list_t * baseMethodList;    /* 本次实现方法列表 */

protocol_list_t * baseProtocols;   /* 本次实例协议列表 */

const ivar_list_t * ivars;        /* 本次实例变量列表 */

const uint8_t * weakIvarLayout;    /*本次 弱引用变量布局 */

property_list_t *baseProperties;   /* 本次属性列表 */

/* 省略各种方法 */

}

这个结构体 class_rw_t 中flags存放着运行期的一系列标识位,class_ro_t 是在编译期确定的结构,里面存放着实例变量的内存布局,这也是为什么在类定义好,不能在运行期加入实例变量的原因(通过 objc_allocateClassPair 除外,但是当调用 objc_registerClassPair 后也不允许加入实例变量),通过clang -rewrite-objc 可以看到大量的class_ro_t结构体定义,或者通过otool工具也可以查看编译后的 class_ro_t 结构。

class_rw_t 中 methods存放了所有本次定义的方法以及分类的方法,分类的方法加入到了数组的最前端,这也是为什么分类方法会覆盖掉类原始定义的方法,因为在通过LC_XXX命令加载镜像时,_read_images 会先加载类定义的方法,然后在加载分类的方法。

实验: 使用 otool -o 输出 iOS app 段,可以明显看到 class_ro_t 定义

/* 使用otool -o 输出iOS app 中的段 */

Contents of (__DATA,__objc_classlist) section

014a8048 0x16a2200

isa 0x16a2214

superclass 0x16ba2b0

cache 0x0

vtable 0x0

data 0x14ace5c (struct class_ro_t *)

flags 0x90

instanceStart 4

instanceSize 8

ivarLayout 0x0

name 0x1108c74 HNAHiHomePageControl

baseMethods 0x14acdf8 (struct method_list_t *)

entsize 12

count 4

name 0x1036ddc initWithFrame:

types 0x11248c5 @24@0:4{CGRect={CGPoint=ff}{CGSize=ff}}8

imp 0xaa21

name 0x1036e6a drawRect:

types 0x11248ee v24@0:4{CGRect={CGPoint=ff}{CGSize=ff}}8

imp 0xaa6d

name 0x1036e74 dotCornerRadius

types 0x1124917 f8@0:4

imp 0xacf1

name 0x1036e84 setDotCornerRadius:

types 0x112491e v12@0:4f8

imp 0xad01

baseProtocols 0x0

ivars 0x14ace30

entsize 20

count 1

offset 0x168eda8 4

name 0x1036e98 _dotCornerRadius

type 0x1124928 f

alignment 2

size 4

weakIvarLayout 0x0

baseProperties 0x14ace4c

entsize 8

count 1

name 0x117a230 dotCornerRadius

attributes 0x117a240 Tf,N,V_dotCornerRadius

Meta Class

isa 0x0

superclass 0x16ba2c4

cache 0x0

vtable 0x0

data 0x14acdd0 (struct class_ro_t *)

flags 0x91 RO_META

instanceStart 20

instanceSize 20

ivarLayout 0x0

name 0x1108c74 HNAHiHomePageControl

baseMethods 0x0 (struct method_list_t *)

baseProtocols 0x0

ivars 0x0

weakIvarLayout 0x0

baseProperties 0x0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值