一个 Person 对象、一个 Student 对象占用多少内存空间?
Person 和 Student 对象实际占用内存 16bytes,系统分配内存也是 16bytes。(注:这里实际占用为 16bytes 是因为结构体内存对齐)
- 系统分配了16个字节给NSObject对象(通过
**malloc_size**
函数获得)- NSObject对象内部只使用了8个字节的空间(可以通过
**class_getInstanceSize**
函数获得)
OC对象的本质
Objective-C 代码的底层都是通过 C/C++ 实现,所以 Objective-C 面向对象是基于 C/C++ 数据结构实现。 下图为OC语言转换成机器语言的几个过程。
通过终端指令:(注:如果需要链接其他框架,使用 -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(实际分配的)
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;
}
对象类型
Instance对象 & Class对象 & Meta-Class对象
Instance 对象(实例对象)
> Instance 对象在内存中存储的信息包括 |
- isa 指针
- 其他成员变量
| | |Class 对象(类对象)
|Meta-Class 对象(元类对象)
| | 每个类在内存中有且仅有一个 Class 对象。
Class 对象在内存中存储的信息包括:| 每个类在内存中也是有且仅有一个 Meta-Class 对象。
objectMetaClass 是 NSObject 的 meta-class 对象(元类对象)Meta-Class 对象在内存中存储的信息包括:| | ```cpp Class objectMetaClass = object_getClass([NSObject class]); // Runtime API
// 注:以下获取的是 objectClass 是 Class 对象,并不是 Meta-Class 对象 Class objectClass = [[NSObject class] class];
| |
| **Class、Meta-Class 对象的本质结构都是 struct objc_class**<br /> | |
| <br />- **Instance 的 isa 指向 Class**。当调用对象方法的时,通过 Instance 的 isa指针找到 Class,最后找到 **对象方法** 的实现进行调用。<br />- **Class 的 isa 指向 Meta-Class**。当调用对象方法的时,通过 Class 的 isa指针找到 Meta-Class,最后找到 **类方法** 的实现进行调用。<br /> |
| --- |
|  |
| <br />- Instance 调用对象方法的轨迹:**isa 找到 Class,方法不存在,就通过superclass 找父类**。<br />- Class 调用类方法的轨迹:**isa 找 Meta-Class,方法不存在,就通过 superclass 找父类**<br /> |
| --- |
|  |
**对象的isa指针指向哪里?**
> - instance对象的isa指向class对象
> - class对象的isa指向meta-class对象
> - meta-class对象的isa指向基类的meta-class对象
**OC的类信息存放在哪里?**
> - 对象方法、属性、成员变量、协议信息,存放在class对象中
> - 类方法,存放在meta-class对象中
> - 成员变量的具体值,存放在instance对象
<a name="ctuyJ"></a>
## super的本质
<a name="xBy3C"></a>
## 
<a name="AHCWJ"></a>
## 窥探 struct objc_class 的结构
[objc4源码下载](https://opensource.apple.com/tarballs/objc4/)
> #include <runtime.h>
```cpp
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
include
typedef struct objc_class *Class;
/// 实例类
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
include
// Class 类
struct objc_class : objc_object {
Class superclass;
cache_t cache; // 方法缓存
class_data_bits_t bits; // 用于获取具体的类信息
...
};
include
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 {...} // 协议列表
}
include
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;
...
}