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     0x00007ffffffffff8UL class_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

  

Objective-C RunTime 学习笔记 之 基础结构体的更多相关文章

  1. Go学习笔记07-结构体与方法

    Go学习笔记07-结构体与方法 Go语言 面向对象 结构的定义与创建 面向对象 Go语言只支持封装,不支持继承和多态. Go语言中只有struct,即结构体:没有class. 结构的定义与创建 pac ...

  2. C语言学习笔记10-结构体、枚举、联合体

    C语言学习笔记10-结构体.枚举.联合体    待传

  3. 我的runtime学习笔记

    0.简介: OC方法不同于C语言函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用. 至于其他理论上的东西不必讲太多,编程讲的就 ...

  4. Object C学习笔记20-结构体

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  5. C#学习笔记之结构体

    1.概述 结构是一种与类相似的数据类型,不过它较类更为轻量,一般适用于表示类似Point.Rectangle.Color的对象.基本上结构能办到的类全都能办到,但在某些情况下使用结构更为合适,后面会有 ...

  6. Object C学习笔记20-结构体(转)

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  7. contiki学习笔记---process结构体

    process,字面意义,进程,看看它的结构 struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #def ...

  8. runtime学习笔记

    获取属性objc_property_t * propertys = class_copyPropertyList(clazz, &outCount); 获取属性名NSString * key ...

  9. 《PHP7底层设计与源码实现》学习笔记2——结构体对齐

    书里给了一段代码,假如有个结构体如下: struct test {     char a;     int b;     long c;     void* d;     int e;     cha ...

随机推荐

  1. Faster-RCNN 算法解读(转)

    论文:<Faster R-CNN: Towards Real-Time ObjectDetection with Region Proposal Networks> 摘要:算法主要解决两个 ...

  2. WebRTC的视频解码原理简析

    WebRTC的视频部分,包含采集.编解码(I420/VP8).加密.媒体文件.图像处理.显示.网络传输与流控(RTP/RTCP)等功能. 视频采集---video_capture:       源代码 ...

  3. Java中Access restriction:····的解决方法

    http://blog.csdn.net/bit2012_2015/article/details/22798779 ————————————————————————————————————————— ...

  4. 第四百一十二节,python接口,抽象方法抽象类

    Python接口 在Python中所谓的接口,有两种,一种是通过url访问的api接口 一种是一个对象的接口 构造接口 class Ijiekou: """ 定义一个约束 ...

  5. Adding ASP.NET MVC5 Identity Authentication to an existing project

    Configuring Identity to your existing project is not hard thing. You must install some NuGet package ...

  6. store.state

    https://blog.csdn.net/qq_38658567/article/details/82847758

  7. HTTP Headers 信息

    点开一个条目,可以查看请求的详细信息: General —— 通用信息 Request URL:请求的URL     Request Method:请求的方法     Status Code:响应状态 ...

  8. 这样使用 GPU 渲染 CSS 动画(转)

    大多数人知道现代网络浏览器使用GPU来渲染部分网页,特别是具有动画的部分. 例如,使用transform属性的CSS动画看起来比使用left和top属性的动画更平滑. 但是如果你问,“我如何从GPU获 ...

  9. java.io.UTFDataFormatException: encoded string too long:

    java.io.UTFDataFormatException: encoded string too long: 259553 bytes 按如下修改可避开此问题. - output.writeUTF ...

  10. date格式互转

    +"%Y/%m/%d-%H:%M:%S" date -d "2017/11/21 17:02:09" +%s