iOS底層-9:對象方法與類方法存儲

根據(jù)新的開源代碼钟病,類的結(jié)構(gòu)發(fā)生了改變蛇更,從這里開始我將采用新的objc-781源碼

鏈接: https://pan.baidu.com/s/1hKjeORBKUK58f-4v0DMU6A
密碼: 8ejw

前面已經(jīng)分析了類的內(nèi)存結(jié)構(gòu)戒良,本文主要用來論證對象方法存放在類中们拙,類方法存放在元類中编兄。

@interface LRPerson : NSObject

@property (nonatomic,copy) NSString *name;

- (void)sayHello;

+ (void)sayHappy;

@end

@implementation LRPerson

- (void)sayHello {}

+ (void)sayHappy {}

@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        LRPerson *p  = [LRPerson alloc];
        p.name = @"LR";
        
        NSLog(@"Hello, World!");
    }
    return 0;
}
  • NSLog處打上斷點也搓,開始LLDB調(diào)試
  • x/4gx LRPerson.class
(lldb) x/4gx LRPerson.class
0x100002260: 0x0000000100002238 0x00000001003f0140
0x100002270: 0x000000010125c7d0 0x0001801c00000003
(lldb) 
  • p (class_data_bits_t *)0x100002280
(lldb) p (class_data_bits_t *)0x100002280
(class_data_bits_t *) $1 = 0x0000000100002280
(lldb) 
  • p $1->data()
(lldb) p $1->data()
(class_rw_t *) $2 = 0x000000010125c770
(lldb) 
  • p $2->methods()
(lldb) p $2->methods()
(const method_array_t) $3 = {
  list_array_tt<method_t, method_list_t> = {
     = {
      list = 0x00000001000020e8
      arrayAndFlag = 4294975720
    }
  }
}
(lldb) 
  • p $3.list
(lldb) p $3.list
(method_list_t *const) $4 = 0x00000001000020e8
(lldb) 
  • p *$4
(lldb) p *$4
(method_list_t) $5 = {
  entsize_list_tt<method_t, method_list_t, 3> = {
    entsizeAndFlags = 26
    count = 4
    first = {
      name = "sayHello"
      types = 0x0000000100000f5a "v16@0:8"
      imp = 0x0000000100000d80 (KCObjc`-[LRPerson sayHello] at main.m:22)
    }
  }
}
(lldb) 

我們發(fā)現(xiàn)count = 4刑棵,總共有4個方法巴刻,分別打印出來

  • p $5.get(0)
(lldb) p $5.get(0)
(method_t) $7 = {
  name = "sayHello"
  types = 0x0000000100000f5a "v16@0:8"
  imp = 0x0000000100000d80 (KCObjc`-[LRPerson sayHello] at main.m:22)
}
(lldb) 
  • p $5.get(1)
(lldb) p $5.get(1)
(method_t) $8 = {
  name = ".cxx_destruct"
  types = 0x0000000100000f5a "v16@0:8"
  imp = 0x0000000100000d90 (KCObjc`-[LRPerson .cxx_destruct] at main.m:20)
}
  • p $5.get(2)
(lldb) p $5.get(2)
(method_t) $9 = {
  name = "name"
  types = 0x0000000100000f6e "@16@0:8"
  imp = 0x0000000100000dc0 (KCObjc`-[LRPerson name] at main.m:12)
}
  • p $5.get(3)
(lldb) p $5.get(3)
(method_t) $10 = {
  name = "setName:"
  types = 0x0000000100000f76 "v24@0:8@16"
  imp = 0x0000000100000df0 (KCObjc`-[LRPerson setName:] at main.m:12)
}
  • p $5.get(4)
(lldb) p $5.get(4)
Assertion failed: (i < count), function get, file /Users/liuyang/Desktop/可編譯objc源碼/runtime/objc-runtime-new.h, line 438.
error: Execution was interrupted, reason: signal SIGABRT.

此時數(shù)組越界。
我們可以看到對象方法 sayHello蛉签,屬性的settergetter方法胡陪,還有cxx_destruct析構(gòu)方法,都存放在class_rw_tmethod_list_t中碍舍,唯獨不見類方法+ (void)sayHappy;的蹤影柠座。

借助machoView分析類方法

1.machoView下載
鏈接: https://pan.baidu.com/s/1guWQKZV0SoX3umoBSHaukw
密碼: gqio

2.編譯生成可執(zhí)行文件

  • 我們的代碼編譯會生成一個黑色可執(zhí)行文件,Show in Finder -> 刪除 -> command+b編譯會重新生成
    image.png
image.png

3.借助machoView分析
編譯之后片橡,其實我們的整個數(shù)據(jù)都已經(jīng)加載到內(nèi)存中了妈经,將黑色可執(zhí)行文件拖入machoView中,我們可以在Functions區(qū)域找到所有的對象方法和類方法捧书,類方法的的確確已經(jīng)加載到內(nèi)存中了吹泡,那么method_list_t為什么找不到類方法?類方法存儲在哪里鳄厌?

image.png

其實OC編譯到底層荞胡,并不會區(qū)分對象方法和類方法,我們在源碼中也沒有找到instance_ method_list_t或者class_ method_list_t了嚎,在底層只有方法泪漂。對象方法存在類里面,以此為依據(jù)我們可以大膽假設(shè)歪泳,類方法是否存在元類里面萝勤?
下面我們用LLDB來探索

LLDB探索類方法是否存儲在元類中

  • x/4gx p.class 拿到類
(lldb) x/4gx p.class
0x100002260: 0x0000000100002238 0x00000001003f0140
0x100002270: 0x00000001011040a0 0x0001801c00000007
(lldb) 
  • p/x 0x0000000100002238 & 0x00007ffffffffff8ULL 拿到元類指針地址
(lldb) p/x 0x0000000100002238 & 0x00007ffffffffff8ULL
(unsigned long long) $1 = 0x0000000100002238
  • po 0x0000000100002238驗證確實是元類
(lldb) po 0x0000000100002238
LRPerson

(lldb) 
  • x/4gx 0x0000000100002238
(lldb) x/4gx 0x0000000100002238
0x100002238: 0x00000001003f00f0 0x00000001003f00f0
0x100002248: 0x000000010155f840 0x0001e03500000003
(lldb) 
  • p (class_data_bits_t *)0x100002238 指針偏移、強轉(zhuǎn)得到class_data_bits_t
(lldb) p (class_data_bits_t *)0x100002238
(class_data_bits_t *) $4 = 0x0000000100002238
(lldb) 
  • p $4->data() 拿到class_rw_t
(lldb) p $4->data()
(class_rw_t *) $5 = 0x00000001003f00f0
(lldb) 
  • p $5->methods() 拿到method_array_t
(lldb) p $5->methods()
(const method_array_t) $6 = {
  list_array_tt<method_t, method_list_t> = {
     = {
      list = 0x00000001012040e4
      arrayAndFlag = 4313858276
    }
  }
}
(lldb) 
  • p $6.list拿到method_list_t
(lldb) p $6.list
(method_list_t *const) $7 = 0x00000001012040e4
(lldb) 
  • p *$7 讀取$7
(lldb) p *$7
(method_list_t) $8 = {
  entsize_list_tt<method_t, method_list_t, 3> = {
    entsizeAndFlags = 26
    count = 1
    first = {
      name = "sayHappy"
      types = 0x0000000100000f5a "v16@0:8"
      imp = 0x0000000100000d70 (KCObjc`+[LRPerson sayHappy] at main.m:24)
    }
  }
}
(lldb) 

類方法sayHappy正在其中呐伞,如此證明類方法確實存在于元類里敌卓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市伶氢,隨后出現(xiàn)的幾起案子趟径,更是在濱河造成了極大的恐慌,老刑警劉巖癣防,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜗巧,死亡現(xiàn)場離奇詭異,居然都是意外死亡蕾盯,警方通過查閱死者的電腦和手機幕屹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人望拖,你說我怎么就攤上這事渺尘。” “怎么了说敏?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵鸥跟,是天一觀的道長。 經(jīng)常有香客問我盔沫,道長锌雀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任迅诬,我火速辦了婚禮腋逆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘侈贷。我一直安慰自己惩歉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布俏蛮。 她就那樣靜靜地躺著撑蚌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搏屑。 梳的紋絲不亂的頭發(fā)上争涌,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機與錄音辣恋,去河邊找鬼亮垫。 笑死,一個胖子當(dāng)著我的面吹牛伟骨,可吹牛的內(nèi)容都是我干的饮潦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼携狭,長吁一口氣:“原來是場噩夢啊……” “哼继蜡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逛腿,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤稀并,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后单默,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碘举,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年雕凹,在試婚紗的時候發(fā)現(xiàn)自己被綠了殴俱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡枚抵,死狀恐怖线欲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情汽摹,我是刑警寧澤李丰,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站逼泣,受9級特大地震影響趴泌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拉庶,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一嗜憔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氏仗,春花似錦吉捶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至慷蠕,卻和暖如春珊拼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背流炕。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工澎现, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人每辟。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓昔头,卻偏偏與公主長得像,于是被迫代替她去往敵國和親影兽。 傳聞我的和親對象是個殘疾皇子揭斧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容