(十六) 你好耻台,DTrace

1. 你好空免,DTrace

DTrace可以使用prob鉤住一個(gè)函數(shù)或一組函數(shù)∨璧ⅲ可以執(zhí)行自定義操作來查詢特定進(jìn)程中的信息蹋砚。如果曾經(jīng)使用過Instruments應(yīng)用程序,那么它下面的許多功能都是由DTrace提供的摄杂。

1.2 初識(shí)DTrace

打開模擬器和終端窗口:

sudo dtrace -n 'objc$target:*ViewController::entry' -p `pgrep SpringBoard`

加上sudo是因?yàn)?code>DTrace是很強(qiáng)大坝咐,甚至可以查詢電腦上其他用戶的信息。這個(gè)DTrace命令有兩個(gè)選項(xiàng)析恢,name選項(xiàng)(-n)和PID選項(xiàng)(-p)墨坚。

如果輸入的所有內(nèi)容都正確,將在終端窗口中得到類似的輸出
以下內(nèi)容:

dtrace: description 'objc$target:*ViewController::entry' matched 42264 probes

每次探測(cè)命中將打印包含以“ViewController”結(jié)尾的Objective-C類映挂。由于將function字段留空框杜,只要類名以ViewController結(jié)尾,它就會(huì)輸出每個(gè)匹配的Objective-C方法袖肥。

sudo dtrace -n 'objc$target:UIViewController:-viewWillAppear?:entry { ustack(); }' -p `pgrep SpringBoard`
  • *ViewController查詢更改為UIViewController咪辱。
  • -viewWillAppear?添加到了function位置。這個(gè)新的DTrace腳本將只匹配-[UIViewController viewWillAppear:]椎组,而不是匹配任何包含字符串“ViewController”的類的每個(gè)函數(shù)油狂。?表示DTrace中的通配符,它將解析為viewWillAppear:方法中的“:”寸癌。
  • 在一個(gè)大括號(hào)中使用一個(gè)名為ustack()的函數(shù)专筷。每次命中-[UIViewController viewWillAppear:]時(shí)都會(huì)調(diào)用此邏輯。ustack()DTrace的內(nèi)置函數(shù)之一蒸苇。當(dāng)這個(gè)方法被命中時(shí)磷蛹,它會(huì)打印調(diào)用棧。

輸入正確的話會(huì)得到以下輸出:

dtrace: description 'objc$target:UIViewController:-viewWillAppear?:entry ' matched 1 probe

當(dāng)-[UIViewController viewWillAppear:]命中時(shí)溪烤,堆棧跟蹤將在終端中打印出來味咳。

viewWillAppear

當(dāng)objc_msgSend執(zhí)行時(shí),函數(shù)簽名將如下所示:

objc_msgSend(self_or_class, SEL, ...);

可以使用arg0參數(shù)在DTrace中獲取第一個(gè)參數(shù)檬嘀,也就是UIViewController的實(shí)例槽驶。不幸的是,我們只能獲得指針的引用鸳兽,不能運(yùn)行任何Objective-C代碼掂铐,如[arg0 title]

DTrace命令的ustack()函數(shù)之前添加printf("\nUIViewcontroller is: 0x%p\n", arg0);

sudo dtrace -n 'objc$target:UIViewController:-viewWillAppear?:entry
{ printf("\nUIViewcontroller is: 0x%p\n", arg0); ustack(); }' -p `pgrep SpringBoard`

dtrace: description 'objc$target:UIViewController:-viewWillAppear?:entry ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0 142401           -viewWillAppear::entry
UIViewcontroller is: 0x7ff224830000

              UIKitCore`-[UIViewController viewWillAppear:]
              SpringBoard`-[SBIconController viewWillAppear:]+0x2a
              UIKitCore`-[UIViewController _setViewAppearState:isAnimating:]+0x297
              UIKitCore`-[UIViewController __viewWillAppear:]+0x73
              BaseBoardUI`-[UIViewController(BaseBoardUI) bs_beginAppearanceTransition:animated:]+0x64
              BaseBoardUI`-[UIViewController(BaseBoardUI) bs_beginAppearanceTransitionForChildViewController:toVisible:animated:]+0xb6
              SpringBoard`-[SBHomeScreenViewController setIconControllerHidden:]+0x106
              SpringBoard`-[SBUIController restoreContentWithOptions:]+0x54e
              SpringBoard`-[SBUIController beginRequiringContentForReason:options:]+0x125
              SpringBoard`-[SBToAppsWorkspaceTransaction transaction:performTransitionWithCompletion:]+0x10d
              SpringBoard`-[SBSceneLayoutWorkspaceTransaction _beginLayoutTransition]+0x93
              SpringBoard`__55-[SBSceneLayoutWorkspaceTransaction _performTransition]_block_invoke_2+0x3c
              BaseBoard`-[BSBlockTransaction _begin]+0x85
              BaseBoard`__22-[BSTransaction begin]_block_invoke+0xa5
              BaseBoard`-[BSTransaction _preventTransactionCompletionForReason:ignoringAuditHistory:andExecuteBlock:]+0x55
              BaseBoard`-[BSTransaction begin]+0x3b3
              BaseBoard`-[BSTransaction _noteFinishedWork]+0x1fd
              BaseBoard`-[BSTransaction _checkAndReportIfCompleted]+0xc2
              BaseBoard`-[BSTransaction _removeMilestones:ignoringAuditHistory:]+0x498
              BaseBoard`__49-[BSTransaction evaluateMilestone:withEvaluator:]_block_invoke+0x9c

現(xiàn)在在打印出堆棧跟蹤之前,打印對(duì)調(diào)用viewWillAppearUIViewController的引用全陨。如果復(fù)制DTrace的這個(gè)指針的地址并將LLDB附著到SpringBoard爆班,我們會(huì)發(fā)現(xiàn)它指向一個(gè)有效的UIViewController(如果還沒有被釋放的話)。

sudo dtrace -n 'objc$target:::entry { @[probemod] = count() }' -p `pgrep SpringBoard`

暫時(shí)還不會(huì)得到任何輸出辱姨,但是一旦使用Ctrl + C終止這個(gè)腳本蛋济。我們將得到一個(gè)聚合列表,列出了執(zhí)行特定類的方法的所有次數(shù)炮叶。從我的輸出中可以看到碗旅,SpringBoard12878個(gè)由NSObject實(shí)現(xiàn)的方法調(diào)用。

NSObject調(diào)用命中

區(qū)分父類子類的調(diào)用很重要镜悉。例如祟辟,調(diào)用-[UIViewController class]將被視為對(duì)NSObject執(zhí)行的方法總數(shù)的命中。因?yàn)?code>UIViewController沒有重寫Objective-C方法class侣肄,UIViewController的父類UIResponder也沒有重寫旧困。

1.2 DTrace專業(yè)用語

我們可以將探測(cè)視為查詢。這些探測(cè)是DTrace可以在特定進(jìn)程中監(jiān)視的事件稼锅,也可以跨計(jì)算機(jī)全局監(jiān)視吼具。

dtrace -n 'objc$target:NSObject:-description:entry / arg0 != 0 / { @[probemod] = count(): }' -p `pgrep SpringBoard`

這個(gè)例子將監(jiān)視NSObject在名為SpringBoard的進(jìn)程中對(duì)description方法的實(shí)現(xiàn)。此外矩距,一旦description方法開始拗盒,就執(zhí)行邏輯來聚合調(diào)用該方法的次數(shù)。

拆分
  • Probe Description:封裝一組指定0個(gè)或多個(gè)探測(cè)的項(xiàng)锥债。它由provider陡蝇、modulefunctionname組成哮肚,每個(gè)都用冒號(hào)分隔登夫。在冒號(hào)之間省略這些項(xiàng)將導(dǎo)致探測(cè)描述包含所有匹配項(xiàng)。你可以用*?用于模式匹配的運(yùn)算符允趟。?運(yùn)算符將充當(dāng)單個(gè)字符的通配符恼策,而*將匹配任何字符。
  • Provider:provider視為一組代碼或公共功能潮剪。我們將主要使用objcprovider程序來跟蹤Objective-C方法調(diào)用涣楷。objcprovider程序?qū)⒕酆纤蠴bjective-C代碼。

注意:$target關(guān)鍵字是一個(gè)特殊關(guān)鍵字鲁纠,它將匹配我們給DTrace提供的任何PID总棵。某些provider(比如objc)希望提供這個(gè)關(guān)鍵字鳍寂。

$target看作實(shí)際PID的占位符改含,它監(jiān)視特定進(jìn)程中的Objective-C。如果確實(shí)引用了$target占位符迄汛,則必須在DTrace命令中通過-p-c選項(xiàng)標(biāo)志指定目標(biāo)PID捍壤。

通常骤视,如果我們知道確切的PID,這可以通過-pPID完成鹃觉,或者可能通過-p "pgrep NameOFProcess"完成专酗。pgrep命令將查找進(jìn)程名為NameOFProcess的PID,然后返回該P(yáng)ID盗扇,然后將其應(yīng)用于$target變量祷肯。

  • Module:在objc提供程序中,Module部分是指定要觀察的類名的位置疗隶。在這個(gè)意義上佑笋,使用objc提供程序有點(diǎn)獨(dú)特。因?yàn)橥ǔDK用于引用代碼來自的庫斑鼻。事實(shí)上蒋纬,在一些提供商中,根本沒有模塊坚弱!然而蜀备,objc provider的作者選擇使用模塊來引用Objective-C類名。對(duì)于這個(gè)例子來說荒叶,模塊是NSObject碾阁。

  • Function:探測(cè)描述中可以指定要觀察的函數(shù)名。對(duì)于這個(gè)例子來說些楣,函數(shù)是-description瓷蛙。objc provider的作者使用+-來確定Objective-C函數(shù)是類還是實(shí)例方法。如果將函數(shù)更改為+description戈毒,它將查詢?nèi)魏螏в?code>+[NSObject description]的探測(cè)艰猬。

  • Name:這通常指定函數(shù)中探測(cè)的位置。entry表示進(jìn)入函數(shù)埋市,return表示離開函數(shù)冠桃。此外,在objc provider中道宅,還可以指定要在其上創(chuàng)建探測(cè)的任何匯編指令偏移量食听!對(duì)于這個(gè)例子來說,名稱是entry污茵,或者函數(shù)的開始樱报。

  • Predicate:一個(gè)可選表達(dá)式,用于評(píng)估操作是否是action的候選者泞当。把謂詞看作if語句中的條件迹蛤。只有謂詞的計(jì)算結(jié)果為true時(shí),才會(huì)執(zhí)行action部分。如果省略謂詞部分盗飒,則每次對(duì)給定探測(cè)執(zhí)行操作塊嚷量。對(duì)于這個(gè)特定的例子,謂詞是/ arg0 = 0 /逆趣,這意味著只有當(dāng)arg0不是nil時(shí)蝶溶,才會(huì)計(jì)算謂詞后面的內(nèi)容。

  • Action:如果探測(cè)與探測(cè)描述匹配宣渗,并且謂詞的計(jì)算結(jié)果為true抖所,則要執(zhí)行的操作『鄞眩可以執(zhí)行將某些內(nèi)容打印到控制臺(tái)部蛇,或者更高級(jí)的功能。對(duì)于本例咐蝇,操作是@[probemod] = count();代碼涯鲁。

簡(jiǎn)單來說,它的結(jié)構(gòu)是這樣:

provider:module:function:name / predicate / { action }

DTrace可以包含多個(gè)子句有序。這些子句可以使用探測(cè)描述監(jiān)視不同的項(xiàng)抹腿,檢查謂詞中的不同條件,并使用不同的操作執(zhí)行不同的邏輯旭寿。

dtrace -n 'objc$target:NSView:-init*:entry' -p `pgrep -x Xcode`

有一個(gè)objc$target:NSView:-init*:entry的探測(cè)描述警绩,其中包括NSView作為模塊,-init*作為函數(shù)盅称,entry作為名稱肩祥,沒有謂詞和操作。DTrace生成一個(gè)用于跟蹤的默認(rèn)輸出(可以使用-q選項(xiàng)使其保持沉默)缩膝。這個(gè)默認(rèn)輸出僅顯示函數(shù)和名稱混狠。例如,如果在跟蹤-[NSObject init]時(shí)沒有使默認(rèn)DTrace操作靜音疾层,則DTrace輸出將如下所示:

dtrace: description ’objc$target:NSObject:-init:entry’ matched 1 probe
  CPU          ID          FUNCTION:NAME
  2           512130       -init:entry
  2           512130       -init:entry
  2           512130       -init:entry
  2           512130       -init:entry

從輸出來看将饺,跟蹤進(jìn)程時(shí)-[NSObject init]被命中4次。我們可以告訴DTrace使用不同格式的輸出痛黎,方法是將-q選項(xiàng)與一個(gè)打印函數(shù)組合起來予弧,以顯示輸出的其他格式。
-n參數(shù)指定可以采用provider:module:function:name湖饱、module:function:namefunction:name格式的DTrace名稱掖蛤。此外,name選項(xiàng)可以接受可選的探測(cè)子句井厌。這就是為什么要將所有一行腳本內(nèi)容用單引號(hào)括起來傳遞給-n參數(shù)的原因蚓庭。

1.3 列出探測(cè)器

-l將列出在探測(cè)描述中匹配的所有探測(cè)致讥。當(dāng)我們使用-l選項(xiàng)時(shí),DTrace將只列出探測(cè)彪置,而不執(zhí)行任何操作拄踪。這使得-l選項(xiàng)成為一個(gè)很好的工具蝇恶,可以用來學(xué)習(xí)哪些要工作拳魁,哪些不工作。

在構(gòu)建DTrace腳本時(shí)撮弧,我們將再次查看探測(cè)描述并系統(tǒng)地限制其范圍潘懊。請(qǐng)考慮以下情況,但不要執(zhí)行此操作:

sudo dtrace -ln ’objc$target:::’ -p `pgrep -x Finder`

這將在Finder應(yīng)用程序中的每個(gè)Objective-C類贿衍、方法和匯編指令上創(chuàng)建探測(cè)描述授舟。對(duì)于DTrace腳本來說,這是一個(gè)非常糟糕的主意贸辈。最好不要運(yùn)行释树,因?yàn)閷@得大量的命中。

注意:我們向pgrep提供了-x選項(xiàng)擎淤。因?yàn)槲覀兛赡塬@得多個(gè)pid奢啥,這將破壞占位符$target-x選項(xiàng)表示返回與Finder名稱完全匹配的PID嘴拢。如果一個(gè)進(jìn)程有多個(gè)實(shí)例桩盲,可以使用-o-n選項(xiàng)在pgrep中獲得最老的或最新的實(shí)例。

sudo dtrace -ln 'objc$target:NSView::' -p `pgrep -x Finder`

這將列出NSView實(shí)現(xiàn)的每個(gè)方法以及每個(gè)方法中的每個(gè)匯編指令的探測(cè)席吴。仍然是一個(gè)可怕的想法赌结,但至少這個(gè)會(huì)在一秒鐘后打印出來。這有多少個(gè)探測(cè)器孝冒?我們可以通過將輸出發(fā)送到wc命令來獲得答案:

 ~> sudo dtrace -ln 'objc$target:NSView::' -p `pgrep -x Finder` | wc -l
   41307

我們?cè)龠^濾一下:

sudo dtrace -ln 'objc$target:NSView:-initWithFrame?:' -p `pgrep -x Finder`

這將把探測(cè)描述篩選到-[NSView initWithFrame:]中執(zhí)行的每個(gè)匯編指令柬姚。注意到?的用法了嗎?而不是冒號(hào)來指定Objective-C選擇器庄涡。如果使用冒號(hào)伤靠,則DTrace將錯(cuò)誤地分析輸入,認(rèn)為函數(shù)部分已完成啼染,并已轉(zhuǎn)到DTrace探測(cè)中指定名稱宴合。函數(shù)描述的開頭還有-表示這是一個(gè)實(shí)例Objective-C方法。

仍然輸出太多迹鹅,我們只想監(jiān)視-[NSView initWithFrame:]方法的開頭卦洽。

 ~>  sudo dtrace -ln 'objc$target:NSView:-initWithFrame?:entry' -p `pgrep -x Finder`
Password:
   ID   PROVIDER            MODULE                          FUNCTION NAME
1156826    objc358            NSView                   -initWithFrame: entry

1.4 一個(gè)創(chuàng)建DTrace腳本的腳本

在使用DTrace時(shí),不僅要處理異常陡峭的學(xué)習(xí)曲線斜棚,如果遇到構(gòu)建時(shí)或運(yùn)行時(shí)DTrace錯(cuò)誤阀蒂,還要處理一些神秘錯(cuò)誤该窗。

為了幫助您在學(xué)習(xí)DTrace時(shí)減輕這些構(gòu)建問題,這里創(chuàng)建了一個(gè)的小腳本tobjectivec.py(trace Objective-C)蚤霞。這是一個(gè)LLDB Python腳本酗失,會(huì)為我們生成一個(gè)自定義DTrace腳本。

通過tobjectivec.py探索DTrace

運(yùn)行Allocator項(xiàng)目昧绣,然后在調(diào)試器中暫停规肴。

(lldb) tobjectivec -g

通常,tobjectivec腳本將在計(jì)算機(jī)的/tmp/目錄中生成一個(gè)腳本夜畴。但是拖刃,這個(gè)-g選項(xiàng)表示我們正在調(diào)試腳本并將輸出顯示到LLDB,而不是在/tmp/中創(chuàng)建文件贪绘。使用-g(--debug)選項(xiàng)時(shí)兑牡,當(dāng)前腳本將顯示在控制臺(tái)上。這個(gè)沒有額外參數(shù)的tobjectivec.py運(yùn)行將產(chǎn)生以下輸出:

#!/usr/sbin/dtrace -s /* 1 */
#pragma D option quiet /* 2 */
dtrace:::BEGIN { printf("Starting... use Ctrl + c to stop\n"); } /* 3 */
dtrace:::END { printf("Ending...\n" ); }
/* Script content below */
objc$target:::entry /* 5 */
{
    printf("0x%016p %c[%s %s]\n", arg0, probefunc[0], probemod, (string)&probefunc[1]); /* 6 */
}
  1. 執(zhí)行DTrace腳本時(shí)税灌,第一行必須是#均函!/usr/sbin/dtrace-s,否則腳本可能無法正常運(yùn)行菱涤。
  2. 表示在探測(cè)觸發(fā)時(shí)不列出探測(cè)計(jì)數(shù)苞也,也不執(zhí)行默認(rèn)的DTrace操作。相反狸窘,我們將給DTrace設(shè)置自定義操作墩朦。
  3. 這是此腳本中DTrace子句的三分之一。讓DTrace用于監(jiān)視某些DTrace事件翻擒。比如當(dāng)DTrace腳本即將啟動(dòng)時(shí)氓涣。一旦DTrace開始,就打印出“Starting... use Ctrl + c to stop“字符串陋气。
  4. DTrace腳本完成時(shí)劳吠,打印“Ending...”。
  5. 我們感興趣的DTrace探測(cè)描述巩趁。意思是在提供給腳本的進(jìn)程ID中跟蹤找到的所有Objective-C代碼痒玩。
  6. 這個(gè)子句的action部分,輸出觸發(fā)的Objective-C探測(cè)的實(shí)例议慰,然后輸出Objective-C樣式的輸出蠢古。在這里,可以看到使用probefuncprobemod别凹,這將是函數(shù)和模塊的char*表示草讶。DTrace有幾個(gè)可以使用的內(nèi)置變量,probefunc炉菲、probemod堕战、probeprovprobename坤溃。記住,模塊將表示類名嘱丢,而函數(shù)將表示Objective-C方法薪介。這里用到了probemodprobefunc,并以我們習(xí)慣的C語法顯示它越驻。

重新執(zhí)行:

(lldb) tobjectivec
Copied script to clipboard... paste in Terminal

在終端窗口粘貼執(zhí)行:

 ~> sudo /tmp/lldb_dtrace_profile_objc.d -p 73610
Password:
Starting...use Ctrl + c to stop

在Xcode的LLDB中輸入po [NSObject class]

測(cè)試

如果我們隨便玩一玩這個(gè)app會(huì)發(fā)現(xiàn)有大量的輸出汁政。東西太多了,下面我們通過向模塊說明符添加內(nèi)容來過濾一些噪聲伐谈。在LLDB中鍵入以下內(nèi)容:

tobjectivec -m *StatusBar* -g

我們看一下這次的探測(cè)描述:

objc$target:*StatusBar*::entry 
{
    printf("0x%016p %c[%s %s]\n", arg0, probefunc[0], probemod, (string)&probefunc[1]);
}

注意探針的模塊部分是如何改變的烂完。在正則表達(dá)式中试疙,*可以被認(rèn)為是任何我們感興趣的诵棵。當(dāng)探測(cè)進(jìn)入函數(shù)的開頭時(shí),查詢包含任何Objective-C類的區(qū)分大小寫單詞StatusBar的探測(cè)祝旷。在LLDB中履澳,刪除-g選項(xiàng)以便將此腳本復(fù)制到剪貼板,然后重新執(zhí)行該命令怀跛。

(lldb) tobjectivec -m *StatusBar*

終端中粘貼:

 ~> sudo /tmp/lldb_dtrace_profile_objc.d -p 73610
Password:
Starting...use Ctrl + c to stop

跳轉(zhuǎn)到模擬器并使用? + Y切換通話狀態(tài)欄距贷,或使用? + ←? + →旋轉(zhuǎn)模擬器,同時(shí)注意DTrace終端窗口吻谋。再次得到大量的輸出忠蝗。我們可以使用DTrace在代碼上撒下一個(gè)大網(wǎng),并在需要時(shí)快速向下深挖漓拾。

跟蹤調(diào)試命令

我們來觀察一下要調(diào)用多少Objective-C方法才能生成一個(gè)簡(jiǎn)單的Objective-C NSString阁最。在LLDB中,輸入以下內(nèi)容:

(lldb) tobjectivec

然后在LLDB中輸入:

(lldb) po @"hi this is a long string to avoid tagged pointers"

測(cè)試

我們剛剛打印了一個(gè)簡(jiǎn)單的NSString骇两,看看這需要多少Objective-C調(diào)用速种!

返回到LLDB并鍵入以下內(nèi)容:

expression -l swift -O -- class b { }; let a = b()

我們使用Swift調(diào)試上下文創(chuàng)建一個(gè)純Swift類,然后將其實(shí)例化低千。創(chuàng)建這個(gè)類時(shí)配阵,請(qǐng)觀察Objective-C方法調(diào)用。

0x0000000105f81c58 +[_TtCs12_SwiftObject class]
0x00000001088db7f8 +[_TtCs12_SwiftObject initialize]
0x00000001088db7f8 -[_TtCs12_SwiftObject self]

如果把DTrace拋出的地址復(fù)制出來示血,然后po一下棋傍。你會(huì)看到這個(gè)純Swift類調(diào)用了多少Objective-C方法。一個(gè)“純粹的”Swift并不像我們想象的那樣純粹难审,對(duì)吧瘫拣?

跟蹤一個(gè)對(duì)象

我們可以使用DTrace輕松跟蹤特定引用的方法調(diào)用。暫停應(yīng)用程序剔宪,使用LLDB獲取對(duì)UIApplication的引用拂铡。

(lldb) po UIApp
<UIApplication: 0x7ffc65601750>

復(fù)制引用并使用它來構(gòu)建一個(gè)謂詞壹无,該謂詞僅在該引用為arg0時(shí)停止。

(lldb) tobjectivec -g -p 'arg0 == 0x7ffc65601750'

#!/usr/sbin/dtrace -es
#pragma D option quiet
dtrace:::BEGIN { printf("Starting...use Ctrl + c to stop\n"); }
dtrace:::END   { printf("Ending...\n"  ); }
/* Script content below */
objc$target:::entry / arg0 == 0x7ffc65601750 /
{
    printf("0x%016p %c[%s %s]\n", arg0, probefunc[0], probemod, (string)&probefunc[1]);
}

然后去掉-g選項(xiàng):

(lldb) tobjectivec -p 'arg0 == 0x7ffc65601750'

觸發(fā)模擬器中的home按鈕(?+Shift + H)或狀態(tài)欄(? + Y)感帅。
這將打印[UIApplication sharedApplication]實(shí)例上的每個(gè)Objective-C方法調(diào)用斗锭。

是不是輸出太多內(nèi)容了?我們來將內(nèi)容聚合:

(lldb) tobjectivec -g -p 'arg0 == 0x7ffc65601750' -a '@[probefunc] = count()'

#!/usr/sbin/dtrace -es
#pragma D option quiet
dtrace:::BEGIN { printf("Starting...use Ctrl + c to stop\n"); }
dtrace:::END   { printf("Ending...\n"  ); }
/* Script content below */
objc$target:::entry / arg0 == 0x7ffc65601750 /
{
    @[probefunc] = count()
}

在不使用-g選項(xiàng)的情況下重新運(yùn)行上面的tobjectivec命令失球,然后將剪貼板內(nèi)容粘貼到終端并在LLDB中繼續(xù)執(zhí)行岖是。這時(shí)終端中尚未顯示任何內(nèi)容。但DTrace正在悄悄地聚合發(fā)送到UIApplication實(shí)例的每個(gè)方法实苞。

在模擬器中隨意玩一玩豺撑,獲取發(fā)送到UIApplication的方法的正常計(jì)數(shù)。一旦使用通常的Ctrl + C終止腳本黔牵,DTrace將打印應(yīng)用于UIApplication實(shí)例的所有Objective-C方法的總數(shù)聪轿。

其他DTrace小技巧

追蹤所有對(duì)象的所有初始化方法:

(lldb) tobjectivec -f ?init*

檢測(cè)進(jìn)程內(nèi)通信相關(guān)的邏輯(比如,Webviews猾浦、keyboards等等):

(lldb) tobjectivec -m NSXPC*

打印出在iOS設(shè)備上處理開始觸摸事件的UIControl的子類 :

(lldb) tobjectivec -m UIControl -f -touchesBegan?withEvent?
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陆错,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子金赦,更是在濱河造成了極大的恐慌音瓷,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夹抗,死亡現(xiàn)場(chǎng)離奇詭異绳慎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)漠烧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門杏愤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沽甥,你說我怎么就攤上這事声邦。” “怎么了摆舟?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵亥曹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我恨诱,道長(zhǎng)媳瞪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任照宝,我火速辦了婚禮蛇受,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厕鹃。我一直安慰自己兢仰,他們只是感情好乍丈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著把将,像睡著了一般轻专。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上察蹲,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天请垛,我揣著相機(jī)與錄音,去河邊找鬼洽议。 笑死宗收,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亚兄。 我是一名探鬼主播混稽,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼儿捧!你這毒婦竟也來了荚坞?” 一聲冷哼從身側(cè)響起挑宠,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤菲盾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后各淀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懒鉴,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年碎浇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了临谱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奴璃,死狀恐怖悉默,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苟穆,我是刑警寧澤抄课,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站雳旅,受9級(jí)特大地震影響跟磨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攒盈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一抵拘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧型豁,春花似錦僵蛛、人聲如沸尚蝌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驼壶。三九已至,卻和暖如春喉酌,著一層夾襖步出監(jiān)牢的瞬間热凹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工泪电, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留般妙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓相速,卻偏偏與公主長(zhǎng)得像碟渺,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子突诬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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