Loading

iOS 底层原理 | OC 对象的本质

一、Objective-C 的本质

Objective-C 代码的底层都是通过 C/C++ 实现,所以 Objective-C 面向对象是基于 C/C++ 数据结构实现。 下图为OC语言转换成机器语言的几个过程。

二、Objective-C 对象本质

通过终端指令:(注:如果需要链接其他框架,使用 -framework 参数。)

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

将 OC 代码转为 C++ 代码,得 NSObject 底层结构:

struct NSObject_IMPL {
    Class isa;
};

Class 是一个指向对象的结构体指针

typedef struct objc_class *Class;

所以 NSObject 是一个结构体,初始内部只有一个指向对象的结构体指针 isa。 由于 iOS 为64位系统,所以一个指针占 8bytes( 1byte = 8bit ),但是实际上系统给它分配了 16bytes 的内存空间。

NSLog(@"%zd",class_getInstanceSize([NSObject class])); //实例对象的成员所占用的大小 8bytes(实际使用的) 
NSLog(@"%zd",malloc_size((__bridge const void *)(obj))); //整个结构体占用的是 16bytes(实际分配的)

OC 源码中所有对象至少分配 16 bytes

size_t instanceSize(size_t extraBytes) {
    size_t size = alignedInstanceSize() + extraBytes;
    // CF requires all objects be at least 16 bytes.
    if (size < 16) size = 16;
    return size;
}

思考

一个 Person 对象、一个 Student 对象占用多少内存空间?

Person 和 Student 对象实际占用内存 16bytes,系统分配内存也是 16bytes。(注:这里实际占用为 16bytes 是因为结构体内存对齐

三、Objective-C 对象分类

  • Instance 对象(实例对象)
  • Class 对象(类对象)
  • Meta-Class 对象(元类对象)

1. Instance 对象(实例对象)

Instance 对象在内存中存储的信息包括

  • isa 指针
  • 其他成员变量

2. Class 对象(类对象)

每个类在内存中有且仅有一个 Class 对象
Class 对象在内存中存储的信息包括:

3. Meta-Class 对象(元类对象)

每个类在内存中也是有且仅有一个 Meta-Class 对象
objectMetaClassNSObject 的 meta-class 对象(元类对象)。

Class objectMetaClass = object_getClass([NSObject class]); // Runtime API

// 注:以下获取的是 objectClass 是 Class 对象,并不是 Meta-Class 对象
Class objectClass = [[NSObject class] class];

Meta-Class 对象在内存中存储的信息包括:

四、isa 指针 和 superclass 指针

1. isa 指针

  • Instance 的 isa 指向 Class。当调用对象方法的时,通过 Instance 的 isa指针找到 Class,最后找到 对象方法 的实现进行调用。
  • Class 的 isa 指向 Meta-Class。当调用对象方法的时,通过 Class 的 isa指针找到 Meta-Class,最后找到 类方法 的实现进行调用。

    从 64bit 开始,isa 需要进行一次位运算,才能计算出真实地址,OC 源码中定义的 ISA_MASK。
# if __arm64__
#   if __has_feature(ptrauth_calls) || TARGET_OS_SIMULATOR
#     define ISA_MASK        0x007ffffffffffff8ULL
#   else
#     define ISA_MASK        0x0000000ffffffff8ULL
#   endif
# elif __x86_64__
#   define ISA_MASK        0x00007ffffffffff8ULL
# else
#   error unknown architecture for packed isa
# endif

Class、Meta-Class 对象的本质结构都是 struct objc_class

2. Class 对象的 superclass 指针

当 Instance 对象要调用父类的 对象方法 时,会先通过 isa 找到 Instance 对象的 Class,然后通过 superclass 找到 Instance 对象父类的 class,最后找到 对象方法 的实现进行调用。

3. Meta-Class 对象的 superclass 指针

当Instance 对象的 Class 要调用 Instance 父类对象的 类方法 时,会先通过 isa 找到 Instance 对象的 Meta-Class,然后通过 superclass 找到Instance 父类对象的 Meta-Class,最后找到 类方法 的实现进行调用。

4. 总结 isa 指针和 superclass 指针

  • Instance 调用对象方法的轨迹:isa 找到 Class,方法不存在,就通过superclass 找父类
  • Class 调用类方法的轨迹:isa 找 Meta-Class,方法不存在,就通过 superclass 找父类

5. 窥探 struct objc_class 的结构

objc4源码下载
#include <runtime.h>

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

#include <objc/objc.h>

typedef struct objc_class *Class;
/// 实例类
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

#include <objc-runtime-new.h>

// Class 类
struct objc_class : objc_object {
   Class superclass;
   cache_t cache;         // 方法缓存
   class_data_bits_t bits; // 用于获取具体的类信息
   ...
};

bits & FAST_DATA_MASK 得到 class_rw_t 数据地址。得
#include <objc-runtime-new.h>

struct class_rw_t {
    uint32_t flags;
    Class firstSubclass;
    Class nextSiblingClass;
    explicit_atomic<uintptr_t> ro_or_rw_ext;
    ...
public:
    ...
    const class_ro_t *ro() const {...}
    const method_array_t methods() const {...} // 方法列表
    const property_array_t properties() const {...} // 属性列表
    const protocol_array_t protocols() const {...} // 协议列表
}

class_ro_t *ro 内部结构
#include <objc-runtime-new.h>

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize; // instance 对象占用的内存空间
#ifdef __LP64__
    uint32_t reserved;
#endif
    union {
        const uint8_t * ivarLayout;
        Class nonMetaclass;
    };
    explicit_atomic<const char *> name; // 类名
    void *baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars; // 成员变量列表
    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
    ...
}
posted @ 2021-02-11 19:31  QiuZH's  阅读(292)  评论(0编辑  收藏  举报