OC对象的本质

1,013 阅读3分钟

OC的一门面向对象的开发语言,是由C,C++,汇编混编而成,那么对象的本质是什么,在底层的结构是什么样的,值得我们探索。

对象的本质

在main.m中创建一个SwwPerson对象,通过xcrun命令编译成c++

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp

image.png

打开main_arm64.cpp文件,找到SwwPerson,可以看出对象的本质就是结构体,对象的继承就是父类作为成员变量😂,所有对象的结构体的类型都是objc_object

typedef struct objc_object SwwPerson;

struct SwwPerson_IMPL {
	struct NSObject_IMPL NSObject_IVARS;
	NSString *_SwwName;
};

objc_object是只包含一个成员变量isa的结构体

struct objc_object {
    Class _Nonnull isa __attribute__((deprecated));
};

我们常用的id类型,是本质是一个结构体指针

typedef struct objc_object *id;

Class的结构体类型是objc_class,也是一个结构体指针

typedef struct objc_class *Class;

isa

位域

在程序中,某些信息存储时不需要一个完整的字节,只需要几位,为节省存储空间C语言支持“位域”的结构体。下面定义了一个结构体和一个位域,结构体的大小为12字节,位域的大小为4字节(最宽基本类型成员大小的整数倍),位域内部的存储有自己的规则,有兴趣的同学可以自行百度。

//结构体
struct str1
{
    int a;
    int b;
    int c;
};

//位域
struct str2
{
    int a:1;
    int b:2;
    int c:6;
};

联合体(共用体)

联合体union和结构体struct在类型定义、变量定义、使用方法上很相似。但是联合体内部成员是互斥的,他们共用一块内存地址。union的sizeof测到的大小实际是union中各个元素里面占内存最大的那个元素的大小。

union uni
{
    int a;
    int b;
    int c;
}

isa

isa的结构是isa_t,是一个联合体位域,如下为isa_t的简写,bits是一个位域。

union isa_t {
    uintptr_t bits;
    Class cls;
}

arm64架构下的bits

uintptr_t nonpointer        : 1;       是否对 isa 指针开启指针优化  0纯isa指针  1包含其他信息      
uintptr_t has_assoc         : 1;       关联对象标志位,0没有,1存在                   
uintptr_t has_cxx_dtor      : 1;       是否有 C++ 或者 Objc 的析构器,如果有析构函数,则需要做析构逻辑, 如果没有,则可以更快的释放对象
uintptr_t shiftcls          : 33;      存储类指针的值
uintptr_t magic             : 6;       用于调试器判断当前对象是真的对象还是没有初始化的空间                                
uintptr_t weakly_referenced : 1;       对象是否被指向或者曾经指向一个 ARC 的弱变量,没有弱引用的对象可以更快释放。                               
uintptr_t unused            : 1;       暂无使用                           
uintptr_t has_sidetable_rc  : 1;       是否使用sidetable存储引用计数     
uintptr_t extra_rc          : 19       引用计数

在objc4的可调试源码中,使用isa拿出类的指针。

  1. 位移运算(x86架构,shiftclass占44位)

image.png 首先拿到personisa,因为使用的源码调试,所以是x86架构(非M1),shiftclass占44位,又边3位,左边17位。想要只留下shiftclass则需要将isa,先右移3位,再左移20位,再右移17。

  1. ISA_MASK 面具

image.png 拿到personisa,和ISA_MASK做与运算,得到shiftclass