閱讀其他語言:English Português 中文
有許多偵錯器教學可以教您如何設定行斷點、記錄值或計算表達式。雖然這些知識本身就為您提供了許多工具來調試應用程序,但實際場景可能會更複雜一些,並且需要更高級的方法。
在本文中,我們將學習如何在沒有太多專案先驗知識的情況下找到導致 UI 崩潰的程式碼,並即時修復損壞的程式碼。
如果您想遵循此範例,請先複製此儲存庫:https://github.com/flounder4130/debugger-example
假設您有一個複雜的應用程序,當您執行某些操作時該應用程式會崩潰。您知道如何重現錯誤,但困難在於您不知道程式碼的哪一部分負責此功能。
在我們的範例應用程式中,當您按一下按鈕 N 時會發生崩潰。然而,要找到負責此操作的程式碼並不容易:
讓我們看看如何使用偵錯器來找到它。
方法斷點相對於行斷點的優點是它們可以在整個類別層次結構中使用。這對我們的例子有什麼用?
如果您查看範例項目,您將看到所有操作類別均派生自 Action 接口,並具有單一方法:perform()。
在此介面方法上設定方法斷點將在每次呼叫派生方法之一時掛起應用程式。若要設定方法斷點,請按一下宣告該方法的行。
啟動偵錯會話並點選按鈕 N。應用程式在 ActionImpl14 上暫停。現在我們知道這個按鈕對應的程式碼在哪裡了。
雖然在本文中我們的重點是尋找錯誤,但當您想要了解某些內容在大型程式碼庫中如何運作時,此技術也可以為您節省大量時間。
使用方法斷點的方法效果很好,但它是基於我們了解父介面的假設。如果這個假設是錯誤的,或者我們因為其他原因不能使用這種方法怎麼辦?
嗯,我們甚至可以在沒有斷點的情況下做到這一點。按一下 按鈕 N,當應用程式掛起時,請前往 IntelliJ IDEA。從主選單中,選擇執行 | 偵錯操作 | 暫停程式。
應用程式將掛起,允許我們檢查執行緒和變數選項卡中執行緒的當前狀態。這讓我們了解應用程式當時正在做什麼。由於它掛起,我們可以識別導致阻塞的方法並將其追溯到呼叫網站。
這種方法比更傳統的線程轉儲有一些優勢,我們很快就會介紹。例如,它以方便的形式為您提供有關變數的信息,並允許您控製程式的進一步執行。
提示:有關暫停程式的更多提示和技巧,請參閱無斷點調試和Debugger.godMode()
最後,我們可以使用執行緒轉儲,這並不是嚴格意義上的偵錯器功能。無論您是否使用調試器,它都可用。
點選按鈕N。當應用程式崩潰時,請轉到 IntelliJ IDEA。從主選單中,選擇執行 | 偵錯操作 | 取得執行緒轉儲。
探索左側的可用線程,在AWT-EventQueue中,您將看到導致問題的原因。
執行緒轉儲的缺點是它們僅提供者在建立時的狀態快照。您不能使用線程轉儲來探索變數或控製程式執行。
在我們的例子中,我們不需要訴諸線程轉儲。但是,我仍然想提一下這種技術,因為它在其他情況下也很有用,例如當您嘗試調試在沒有調試代理的情況下啟動的應用程式時。
無論調試技術如何,我們都會到達 ActionImpl14。在此類中,有人打算在單獨的執行緒中完成工作,但將 Thread.start() 與 Thread.run() 混淆了,後者在與呼叫程式碼相同的執行緒中執行程式碼。
IntelliJ IDEA 的靜態分析器甚至在設計時警告我們:
在 UI 執行緒上呼叫執行繁重任務(或在本例中休眠很多時間)的方法,並阻止該方法直到該方法完成。這就是為什麼我們在點擊按鈕N後一段時間內無法在UI中執行任何操作。
現在我們已經找到了錯誤的原因,讓我們來修正問題。
我們可以停止程序,重新編譯程式碼,然後再次執行它。然而,僅僅因為做了一個小更改就重新部署整個應用程式並不總是明智的。
讓我們用聰明的方式來做吧。首先,使用建議的快速修復修復代碼:
程式碼準備好後,點選執行 | 偵錯操作 | 重新載入已變更的類別。出現一個氣球,確認新代碼已到達虛擬機器。
讓我們返回應用程式並檢查一下。點選按鈕 N 不再使應用程式崩潰。
提示:請記住,HotSwap 有其限制。如果您對擴展的 HotSwap 功能感興趣,那麼看看 DCEVM 或 JRebel 等高級工具可能是個好主意
使用我們的推理和一些偵錯器功能,我們能夠找到導致專案中 UI 崩潰的程式碼。然後,我們繼續修復程式碼,而不會浪費時間重新編譯和重新分發,這在實際專案中可能會很長。
我希望您發現所描述的技術很有用。讓我知道你的想法!
如果您對更多與調試和分析相關的文章感興趣,請查看我的其他一些文章:
更多內容敬請期待!
以上是調試無響應的應用程式的詳細內容。更多資訊請關注PHP中文網其他相關文章!