要了解 isa 指針先了解下類的定義
在xcode中用快捷鍵Shift+Cmd+O 搜索objc.h 能看到類的定義:
瞭解html
能夠看出:
objc_object:Objective-C對對象的定義, 其質上是結構體對象,其中 isa是它惟一的私有成員變量,即全部對象都有isa指針
Class 是一個 objc_class 結構類型的指針
id是一個 objc_object 結構類型的指針,這也是id能夠指向任何對象的緣由
SEL(方法選擇器)是一個objc_selector結構類型的指針
IMP 先不提ios
再搜runtime.h數組
每一個對象結構體的首個成員是Class類的變量,該變量定義了對象所屬的類,一般稱爲isa指針xcode
super_class:父類,若是該類已是最頂層的根類,那麼它爲NULL。
version:類的版本信息,默認爲0
info:供運行期使用的一些位標識。
instance_size:該類的實例變量大小
ivars:成員變量的數組
struct objc_method_list **methodLists OBJC2_UNAVAILABLE : 方法列表,類目就是經過它添加方法的緩存
struct objc_cache *cache OBJC2_UNAVAILABLE : 方法緩存,對象接到一個消息會根據isa指針查找消息對象,這時會在methodLists中遍歷,若是cache了,經常使用的方法調用時就可以提升調用的效率。架構
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE : 協議鏈表ide
用 64 bit 存儲一個內存地址顯然是種浪費,畢竟不多有那麼大內存的設備。因而能夠優化存儲方案,用一部分額外空間存儲其餘內容。isa 指針第一位爲 1 即表示使用優化的 isa 指針,這裏列出不一樣架構下的 64 位環境中 isa 指針結構:函數
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bits; #if SUPPORT_NONPOINTER_ISA # if __arm64__ # define ISA_MASK 0x00000001fffffff8ULL # define ISA_MAGIC_MASK 0x000003fe00000001ULL # define ISA_MAGIC_VALUE 0x000001a400000001ULL struct { uintptr_t indexed : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 30; // MACH_VM_MAX_ADDRESS 0x1a0000000 uintptr_t magic : 9; uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 19; # define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18) }; # elif __x86_64__ # define ISA_MASK 0x00007ffffffffff8ULL # define ISA_MAGIC_MASK 0x0000000000000001ULL # define ISA_MAGIC_VALUE 0x0000000000000001ULL struct { uintptr_t indexed : 1; uintptr_t has_assoc : 1; uintptr_t has_cxx_dtor : 1; uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000 uintptr_t weakly_referenced : 1; uintptr_t deallocating : 1; uintptr_t has_sidetable_rc : 1; uintptr_t extra_rc : 14; # define RC_ONE (1ULL<<50) # define RC_HALF (1ULL<<13) }; # else // Available bits in isa field are architecture-specific. # error unknown architecture # endif // SUPPORT_NONPOINTER_ISA #endif };
SUPPORT_NONPOINTER_ISA 用於標記是否支持優化的 isa 指針,其字面含義意思是 isa 的內容再也不是類的指針了,而是包含了更多信息,好比引用計數,析構狀態,被其餘 weak 變量引用狀況。判斷方法也是根據設備類型:優化
#if !__LP64__ || TARGET_OS_WIN32 || TARGET_IPHONE_SIMULATOR || __x86_64__ # define SUPPORT_NONPOINTER_ISA 0 #else # define SUPPORT_NONPOINTER_ISA 1 #endif
isa指針會判斷是否支持 TaggedPointer 支持會直接將其指針值做爲引用計數返回ui
TaggedPointer 就是一種優化方式,當承載內容小於8字節時,指針直接儲存承載內容
關於Tagged Pointer 這裏有詳細介紹
http://www.infoq.com/cn/articles/deep-understanding-of-tagged-pointer/
若是當前設備是 64 位環境而且使用 Objective-C 2.0(5s以後就都是64位),那麼「一些」對象會使用其 isa 指針的一部分空間來存儲它的引用計數;不然 Runtime 會使用一張散列表來管理引用計數
64位中isa 指針中變量對應的含義:
associate object : 關聯對象
SEL會依據方法名生成惟一的表示做爲key ,便於查找
IMP指針是指向實現函數的指針,經過SEL取得IMP,objc_msgSend來執行實現方法
objc_msgSend函數在執行方法時不會直接在 isa 指針指向的類的方法列表中遍歷查找可以響應的方法,由於每次都要查找效率過低了,而是優先在緩存(方法列表)中查找,如果找不到再沿着繼承體向上查找。每次匹配到的結果會緩存在"快速映射表"裏,來提升效率,同時objc_msgSend函數用到了"尾調用優化技術",來節約資源,感興趣能夠了解下
https://en.wikipedia.org/wiki/Tail_call
http://kb.cnblogs.com/page/518771/
//引用文章
http://www.cocoachina.com/ios/20151209/14636.html
http://www.cocoachina.com/ios/20150717/12623.html
http://www.cnblogs.com/ioshe/p/5489086.html