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

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

  • 系统分配了16个字节给NSObject对象(通过**malloc_size**函数获得)
  • NSObject对象内部只使用了8个字节的空间(可以通过**class_getInstanceSize**函数获得)

image.png

OC对象的本质

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

image.png

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

  1. xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main_arm64.cpp
  1. // 将 OC 代码转为 C++ 代码,得 NSObject 底层结构:
  2. struct NSObject_IMPL {
  3. Class isa;
  4. };
  5. // Class 是一个指向对象的结构体指针
  6. typedef struct objc_class *Class;

内存大小分配

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

  1. NSLog(@"%zd",class_getInstanceSize([NSObject class])); //实例对象的成员所占用的大小 8bytes(实际使用的)
  2. NSLog(@"%zd",malloc_size((__bridge const void *)(obj))); //整个结构体占用的是 16bytes(实际分配的)
  1. size_t instanceSize(size_t extraBytes) {
  2. size_t size = alignedInstanceSize() + extraBytes;
  3. // CF requires all objects be at least 16 bytes.
  4. if (size < 16) size = 16;
  5. return size;
  6. }

对象类型

Instance对象 & Class对象 & Meta-Class对象

|

Instance 对象(实例对象)

> Instance 对象在内存中存储的信息包括
  • isa 指针
    - 其他成员变量
    | | |

    Class 对象(类对象)

    |

    Meta-Class 对象(元类对象)

    | | 每个类在内存中有且仅有一个 Class 对象
    Class 对象在内存中存储的信息包括:
    image.png | 每个类在内存中也是有且仅有一个 Meta-Class 对象
    objectMetaClass 是 NSObject 的 meta-class 对象(元类对象)Meta-Class 对象在内存中存储的信息包括:
    image.png | | ```cpp Class objectMetaClass = object_getClass([NSObject class]); // Runtime API

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

  1. | |
  2. | **ClassMeta-Class 对象的本质结构都是 struct objc_class**<br />![image.png](https://cdn.nlark.com/yuque/0/2023/png/449231/1675865775424-398cc853-7f3e-4089-8b3c-cf963e5aea0c.png#averageHue=%237da955&clientId=u3b442766-f0a7-4&from=paste&height=273&id=kB0JM&originHeight=878&originWidth=2408&originalType=binary&ratio=1&rotation=0&showTitle=false&size=478100&status=done&style=none&taskId=u40a8dc4a-10ee-4bbd-812c-fb6ba0746f3&title=&width=749.0113525390625) | |
  3. | <br />- **Instance isa 指向 Class**。当调用对象方法的时,通过 Instance isa指针找到 Class,最后找到 **对象方法** 的实现进行调用。<br />- **Class isa 指向 Meta-Class**。当调用对象方法的时,通过 Class isa指针找到 Meta-Class,最后找到 **类方法** 的实现进行调用。<br /> |
  4. | --- |
  5. | ![image.png](https://cdn.nlark.com/yuque/0/2023/png/449231/1675865735590-fe341384-5359-43f0-a333-f9bb6e798010.png#averageHue=%23fffffe&clientId=u3b442766-f0a7-4&from=paste&height=225&id=u797c48ca&originHeight=462&originWidth=1468&originalType=binary&ratio=1&rotation=0&showTitle=false&size=79061&status=done&style=none&taskId=u15d169b8-1224-4fa5-8cf6-d76611b8477&title=&width=716.0056762695312) |
  6. | <br />- Instance 调用对象方法的轨迹:**isa 找到 Class,方法不存在,就通过superclass 找父类**。<br />- Class 调用类方法的轨迹:**isa Meta-Class,方法不存在,就通过 superclass 找父类**<br /> |
  7. | --- |
  8. | ![image.png](https://cdn.nlark.com/yuque/0/2023/png/449231/1675865863718-ca2de1ce-2a20-4827-9d6e-d330117d25e3.png#averageHue=%23f3f3f2&clientId=u3b442766-f0a7-4&from=paste&height=480&id=uf00ce9ff&originHeight=992&originWidth=952&originalType=binary&ratio=1&rotation=0&showTitle=false&size=228708&status=done&style=none&taskId=u08eebe65-1cfa-45c8-9490-5a20cd82308&title=&width=460.7130432128906) |
  9. **对象的isa指针指向哪里?**
  10. > - instance对象的isa指向class对象
  11. > - class对象的isa指向meta-class对象
  12. > - meta-class对象的isa指向基类的meta-class对象
  13. **OC的类信息存放在哪里?**
  14. > - 对象方法、属性、成员变量、协议信息,存放在class对象中
  15. > - 类方法,存放在meta-class对象中
  16. > - 成员变量的具体值,存放在instance对象
  17. <a name="ctuyJ"></a>
  18. ## super的本质
  19. <a name="xBy3C"></a>
  20. ## ![image.png](https://cdn.nlark.com/yuque/0/2023/png/449231/1676472502955-89affa9a-0d4e-4828-88fc-07eb4a4bf765.png#averageHue=%23f8f7f7&clientId=u1d147d5e-73e9-4&from=paste&height=240&id=uaa56d200&originHeight=646&originWidth=1648&originalType=binary&ratio=1.100000023841858&rotation=0&showTitle=false&size=141203&status=done&style=none&taskId=u6a493c9a-f2b8-4f50-ba74-931849cb1c6&title=&width=613.0084838867188)
  21. <a name="AHCWJ"></a>
  22. ## 窥探 struct objc_class 的结构
  23. [objc4源码下载](https://opensource.apple.com/tarballs/objc4/)
  24. > #include <runtime.h>
  25. ```cpp
  26. struct objc_class {
  27. Class _Nonnull isa OBJC_ISA_AVAILABILITY;
  28. };

include

  1. typedef struct objc_class *Class;
  2. /// 实例类
  3. struct objc_object {
  4. Class _Nonnull isa OBJC_ISA_AVAILABILITY;
  5. };

include

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

include

  1. struct class_rw_t {
  2. uint32_t flags;
  3. Class firstSubclass;
  4. Class nextSiblingClass;
  5. explicit_atomic<uintptr_t> ro_or_rw_ext;
  6. ...
  7. public:
  8. ...
  9. const class_ro_t *ro() const {...}
  10. const method_array_t methods() const {...} // 方法列表
  11. const property_array_t properties() const {...} // 属性列表
  12. const protocol_array_t protocols() const {...} // 协议列表
  13. }

include

  1. struct class_ro_t {
  2. uint32_t flags;
  3. uint32_t instanceStart;
  4. uint32_t instanceSize; // instance 对象占用的内存空间
  5. #ifdef __LP64__
  6. uint32_t reserved;
  7. #endif
  8. union {
  9. const uint8_t * ivarLayout;
  10. Class nonMetaclass;
  11. };
  12. explicit_atomic<const char *> name; // 类名
  13. void *baseMethodList;
  14. protocol_list_t * baseProtocols;
  15. const ivar_list_t * ivars; // 成员变量列表
  16. const uint8_t * weakIvarLayout;
  17. property_list_t *baseProperties;
  18. ...
  19. }