1-9.【OC】【基础】Objective-C 对象在内存中的最小结构是什么?

1 阅读2分钟

在 Objective-C 中,一个对象在内存中的最小结构本质上就是一个 C 语言结构体。它的“极简版”只包含一个成员,即指向类信息的指针。


1. 最小结构的定义

在 Runtime 源码(objc.h)中,对象的最小定义是 objc_object 结构体:

C

struct objc_object {
    Class _Nonnull isa; 
};
  • isa 指针: 它是对象的“身份证明”。在 64 位架构下,这个指针占 8 字节
  • 含义: 只要这 8 字节存在,Runtime 就能通过它找到该对象所属的 类(Class) ,进而知道它能响应哪些消息。

2. 实际占用的内存:16 字节

虽然结构体理论上只需要 8 字节,但在实际分配中,Objective-C 对象的最小内存占用是 16 字节

这是由两个层面的限制决定的:

  1. Runtime 限制:allocWithZone: 底层实现中,系统硬编码了对象分配至少为 16 字节。
  2. 内存对齐(Memory Alignment): 为了提高 CPU 读取效率,iOS/macOS 的堆内存分配通常以 16 字节为对齐准则。

3. 对象结构的“进化”:Non-pointer isa

在现代 64 位架构(如 iOS 的 ARM64)中,isa 不再是一个简单的纯指针,而是一个 isa_t 共用体(union)

为了不浪费这 8 字节(64 位)的巨大空间,苹果在其中塞入了大量额外信息,这就是所谓的 Tagged Pointer 思想的延伸:

  • indexed (1 bit): 0 代表纯指针,1 代表里面包含了额外信息。
  • has_assoc (1 bit): 对象是否有关联对象。
  • has_sidetable_rc (1 bit): 引用计数是否过大,需要存到外部哈希表中。
  • shiftcls (33+ bits): 真正的类地址偏移量。
  • extra_rc: 存储对象的引用计数(减 1 后的值)。

这意味着: 一个最简单的对象,其内存不仅存储了“我是谁”,还顺便存储了它的“引用计数”和“是否被弱引用”等状态。


4. 完整的内存布局示意

当你给对象增加成员变量(ivar)时,它们会按顺序排在 isa 指针之后:

偏移量 (Offset)内容说明
0 ~ 7 字节isa存储类地址及状态位(必须有)
8 ~ 15 字节ivar1用户定义的第一个变量(如 int
16 ~ 23 字节ivar2第二个变量(按对齐补齐)

总结

Objective-C 对象的逻辑最小结构是一个 isa 指针,占用 8 字节;但在 物理内存 中,任何一个实例对象至少占用 16 字节