在探索对象alloc的时候。遇到一个很关键信息 isa
,另外对象的本质到底是什么,经过对alloc从底层源码探索后,也应该有一个比较清晰的框架了。
iOS开发用的是clang编译器,我们可以通过将.m
文件clang编译为.cpp
文件(C++)文件。因此看到一些隐藏在后面的内容。
命令行cd
到需要转换文件的文件夹,clang -rewrite-objc main.m -o main.cpp
运行即可,还可以使用xcode
自带的xcrun
,运行xcrun -sdk iphonesimulator clang -rewrite-objc main.m
先初始化一个类,然后生成cpp
文件
得到一个cpp文件。定位到Goodgame。可以看待一个结构体。然后找到objc_object
的实现
objc_object
就是isa,结构体
在int main
函数中,objc_getClass
应该会和类有关系
objc_class
探索到这里, 类
-> objc_object
->objc_class
,而objc_class
是在objc的源码中出现。
objc_class
继承objc_object
,组成
// Class ISA;
这里注释了isa,像是在提醒我们isa是继承来。Class superclass;
指向的父类(类)cache_t cache;
缓存相关,是个结构体,16字节class_data_bits_t bits;
存放数据的地方,bits中有dataclass_rw_t *data() const{...}
等等一大推条件
cache_t
的组成
cache_t
中源码比较多涉及到了方法查找流程,缓存策略,动态扩容,后期再补。
class_rw_t
的实现
const class_ro_t *ro()
包含方法列表、ivars、属性、协议列表const method_array_t methods()
方法列表const property_array_t properties()
属性列表const protocol_array_t protocols()
协议列表
objc_object
ISA_BITFIELD
中
这段宏定义 可以看到,isa是一个联合体,有arm64 架构有x86_64架构
arm64架构下
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 1
# define ISA_BITFIELD
uintptr_t nonpointer : 1; //0普通指针,1经过优化的指针,使用位域存更多信息
uintptr_t has_assoc : 1; //是否关联引用
uintptr_t has_cxx_dtor : 1;// 是否C++析构函数或者dealloc。有的话释放更快
uintptr_t shiftcls : 33;//存放Class、Meta—Class对象的内存地址 /*MACH_VM_MAX_ADDRESS 0x1000000000*/
uintptr_t magic : 6;//用于调式时对象是否完成初始化
uintptr_t weakly_referenced : 1;//是否内弱引用指向
uintptr_t unused : 1;// 是否正在释放
uintptr_t has_sidetable_rc : 1; //释放需要使用sidetable来存储引用计数
uintptr_t extra_rc : 19; //引用计数能够用19个二进制存储
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
x86_64
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
# define ISA_HAS_CXX_DTOR_BIT 1
# define ISA_BITFIELD
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 44; /*MACH_VM_MAX_ADDRESS 0x7fffffe00000*/ \
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t unused : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 8
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
简单做个对比shiftcls``extra_rc
两个值不同。
has_sidetable_rc
sidetables
中包含N个sidetable
。每个sidetable
,包含spinlock_t slock;
自旋锁.RefcountMap refcnts;
引用计数.weak_table_t weak_table;
弱引用表。为了数据安全而设计的。sidetable 单线程进行,效率低。多张表的sidetable,加上各自的自旋锁,速度快了,效率也高。
挖个坑 如何操作引用计数,从而牵引出内存管理、ARC