isa 指標各位域所指代含義
union isa_t
isa_t(uintptr_t value) : bits(value)
class cls;
uintptr_t bits;
#if defined(isa_bitfield)
struct ;
#endif
};
nonpointer 標記是否是nonpointerisa 如果不是就單純的指向類 如果是就還有下邊的一些資訊 0 是 純的isa。1 是nonpointerisa
has_assoc 是否有關聯物件
has_cxx_dtor 判斷是否有c++或者objc的析構器。如果沒有可以快速釋放
shiftcls 開啟指標優化 儲存類指標
magic 用於除錯判斷當前物件時真的物件還是沒有初始化的空間
weakly_referenced 標記當前物件是否被指向或者曾經指向乙個弱引用物件 如果沒有可以盡快釋放
deallocating 是否正在釋放
has_sidetable_rc 標記當前有沒有sidetable 如果沒有可以更快的釋放
extra_rc 表示當前物件的引用計數 如果小於10 就儲存在這裡 如果大於10 情況變得複雜 要往sidetable中放
isa 指向總結
很經典的那張圖 不再放了 這裡語言總結一下
isa: 類物件的isa指向 類 類的isa指向元類 元類的isa指向跟元類 根源類的isa指向自己
父子關係 子類繼承父類 父類繼承跟類。子元類繼承父元類父元類繼承跟元類 跟元類繼承nsobject
isa 初始化過程
objc_object::initisa(class cls, bool nonpointer, bool hascxxdtor)
else
}
如果不是nonpointer 就是沒有開啟指標優化 直接指向類。如果開始了指標優化 isa中就儲存了其他資訊。給bits has_cxx_dtor 都賦上初始值
isa 驗證
通過下面獲取isa的源** 一步一步驗證
inline class
objc_object::isa()
return (class)isa.bits;
#else
return (class)(isa.bits & 0x00007ffffffffff8);
#endif
}
建立乙個繼承子nsobject的類 people類 建立物件p lldb除錯
p/x p.class
(class) $2 = 0x000000010d3085a8 people 類的記憶體位址
x/4gx p
0x6000004cc330: 0x000000010d3085a8 0x0000000000000000
0x6000004cc340: 0x00007f9df0405820 0x0000000000000000
p 0x000000010d3085a8 & 0x00007ffffffffff8
(long) $4 = 4516251048
p/x $4
(long) $4 = 0x000000010d3085a8
通過$2 和$4 可以發現 兩個位址一摸一樣 所以
p物件的isa指向people 也就是他的類
接著列印類的isa
(lldb) x/4gx $2
0x106c28580: 0x0000000106c28558 0x00007fff89cc4580
0x106c28590: 0x00006000036cf7f0 0x0003801800000003
(lldb) p 0x0000000106c28558 & 0x00007ffffffffff8
(long) $3 = 4408378712
(lldb) po $3
people
people 類的isa還是people 其實是指向元類。 這個地方可以通過 objc_getmetaclass(<#const char * _nonnull name#>) 進行驗證
繼續列印元類的isa
x/4gx $3
0x106c28558: 0x00007fff89cc4558 0x00007fff89cc4558
0x106c28568: 0x00006000036cf7a0 0x0003c03100000003
(lldb) p 0x00007fff89cc4558 & 0x00007ffffffffff8
(long) $4 = 140735505253720
(lldb) po $4
nsobject
people類的isa指向 nsobject根元類
繼續探索 我們列印$4 也就是根元類的父類
po 140735505253720 + 8
根元類的父類是nsobject
ios 類探索
objc_class 原始碼
struct objc_class : objc_object
}
第一步建立people 物件 並且獲取到類
people 類結構
@inte***ce people : nsobject
@property(nonatomic,copy)nsstring *name;
@property(nonatomic,copy)nsstring *location;
@property(nonatomic,assign)int age;
- (void)saygoodby;
+ (void)sayhello;
@end
@implementation people
- (void)saygoodby
+ (void)sayhello
@end
執行一下 命令
people *p = [[people alloc]init];
x/4gx p
0x102e0d730: 0x001d800100002645 0x0000000000000000
0x102e0d740: 0x0000000000000000 0x0000000000000000
(lldb) p 0x001d800100002645 & 0x00007ffffffffff8
(long) $1 = 4294977088
(lldb) po $1
people 此時此刻拿到類 也就是$1
再來看 cache_t
struct cache_t
};
p $13->basemethodlist
(method_list_t *const) $15 = 0x00000001000020d8 拿到方法列表
就可以通過 p $15.get(index) 獲取方法 這個方法是從 entsize_list_tt 結構題中獲得
這裡掉了乙個坑 開始 saygoodby的例項方法沒實現 所以這個列表中一直沒有
(ivar_t) $41 =
$40->get(0)
就把我們的成員變數_dohomeword拿到了
總結
經過探索發現 oc的 類本質上是objc_class 的乙個結構體 儲存了 superclass cache bits 方法列表 屬性列表 變數列表 都存在了 class_rw_t 的結構體中,其中類的成員變數在ivars中 屬性在baseproperties 但是在ivars 中也是可以找到帶 _ 的屬性變數 例項方法 在basemethodlist 中找到 類方法 就在元類中。
類初始化過程
class x class y public class z extends x public static void main string args a zyxxb zyxyc yxyzd xyzx解答 靜態變數 靜態 塊 main方法 非靜態變數 塊 構造方法 初始化過程 1.初始化父類中的靜...
類初始化和例項初始化過程
類初始化過程 乙個類要建立例項需要先載入並初始化該類 main方法所在的類需要先載入和初始化 乙個子類要初始化需要先初始化父類 乙個類初始化就是執行 方法 由靜態類變數賦值 和靜態 塊組成 靜態類變數賦值 和靜態 塊從上往下執行 方法只執行一次 例項初始化過程 例項初始化就是執行 方法 方法可能過載...
C 類指標初始化
上面 的 會列印 a c 類指標定義的時候沒有初始化的時候,居然可以安全的呼叫類內部的成員函式而不出錯。在網上查了一下 初始化為null的類指標可以安全的呼叫不涉及類成員變數的類成員函式而不出錯,但是如果類成員函式中呼叫了類成員變數則會出錯,既然賦值為null的情況都可以使用,那麼自然不初始化的類指...