上一篇類的原理(上)中我們探索了類的屬性以及對(duì)象方法的存儲(chǔ)位置,但是我們?cè)谔剿鬟^程中并沒有找到成員變量和類方法的存儲(chǔ)位置,那么這篇文章我們一起探索下成員變量和類方法的存儲(chǔ)位置。
成員變量
1、我們通過上篇分析后沒有找到成員以及類方法的存儲(chǔ)位置,所以我們繼續(xù)到class_rw_t結(jié)構(gòu)體去分析,最后找到如下函數(shù):
2、那么我們?cè)偃ナ褂迷创a+lldb去調(diào)式一下看看,這個(gè)里面存儲(chǔ)的是什么呢?
3、從上圖打印結(jié)果我們可以看到,在class_rw_t結(jié)構(gòu)體中的ro()方法回調(diào)能夠得到一個(gè)class_ro_t結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體的內(nèi)容比較多,但是經(jīng)過簡(jiǎn)化我們需要的后,大概如下:
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
union {
const uint8_t * ivarLayout;
Class nonMetaclass;
};
void *baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
}
以上就是我們需要的一些基本的成員,能夠得到我們想要的成員變量列表、方法列表,協(xié)議列表,屬性列表等等。
4、到這里我們找到了成員變了存儲(chǔ)的位置,也額外找到一些類的其它結(jié)構(gòu)存儲(chǔ)位置。然后我們看到了一個(gè)baseMethodList,順帶看看這個(gè)?經(jīng)過lldb打印結(jié)果如下:
從以上看出還是只是對(duì)象方法,并沒有我們的類方法,然后我們繼續(xù)去探索類方法的存儲(chǔ)位置。
類方法
1、目前我們已經(jīng)找到了類的屬性、成員變量、對(duì)象方法的存儲(chǔ)位置,這一節(jié)我們探索類方法的存儲(chǔ)位置,我們?cè)陬愔姓疫^了所有與方法有關(guān)系的函數(shù),都沒有找到類方法的存儲(chǔ)位置,那么我們是否有這么一個(gè)猜測(cè),它是否在元類中?因?yàn)榈侥壳盀橹?,沒有想到元類有什么作用。所以帶著好奇心我們?nèi)タ聪略愔械?code>bits。
2、首先我們通過lldb去看下bits中的methods()包含啥?但是我們?cè)趺丛L問到元類呢?很簡(jiǎn)單之前對(duì)象的本質(zhì)這篇文章中有介紹isa_t這個(gè)聯(lián)合體的時(shí)候介紹了一個(gè)掩碼,那么我們通過這個(gè)掩碼就可以得到元類,看下面結(jié)果:
3、從上圖我們可以看到,類方法確實(shí)存儲(chǔ)在了元類中。這個(gè)過程中我們不是拿的KGPerson.class的地址,而是通過isa取模然后地址偏移最后得到的元類,其它的都是和讀取類的操作是一樣的。
4、那么到此我們經(jīng)過兩篇文章的探索,大概分析了類的屬性、成員變量、對(duì)象方法(實(shí)例方法)、類方法的存儲(chǔ)位置。
總結(jié)
經(jīng)過兩篇文章的分析,我們探究了類的屬性、成員變量、類方法、對(duì)象方法的存儲(chǔ)位置,大概了解了一些類的內(nèi)存結(jié)構(gòu)。