當前位置: 妍妍網 > 碼農

掌握 IDEA 這 30 個 Debug 神技,開發、改Bug 效率快10倍

2024-05-14碼農

大家好,我是一航!

寫Bug、改Bug幾乎占據了程式設計師日常工作的絕大部份時間,如果你能掌握一手偵錯程式碼的絕技,相信工作效率必定會得到大振幅的提升;

IDEA 就為我們提供了很多簡單且非常強大的偵錯功能,但是發現有些小夥伴並沒有完全用上,今天就一起來玩一下那些Debug的 奇淫巧計 ;30來個功能及偵錯小技巧,學完後讓你開發偵錯效率提升個10倍!爭取做到早上9點上班,10點就能下班 (小聲說:是晚上10點【手動狗頭】)

本文的目錄:

IDEA的Debug控制台在整個視窗的左下方;

IDEA 偵錯功能說明

  • Show Execution Point

    快捷鍵: Alt + F10

    回到當前啟用的斷點處 ;當你的滑鼠不在斷點所處的行,點選之後,會立馬復位到斷點處;

  • Step Ove

    快捷鍵: F8

    單步偵錯;逐行往下執行,如果執行行有其他方法,不會進入對應的方法;日常Debug用的最多的一個功能

  • Step Into

    快捷鍵: F7

    進入方法體內部。該功能會進入自訂的方法或者三方庫的方法;註意, 不會進入JDK的方法

  • Force Step Into

    快捷鍵: Alt + Shift + F7

    強制進入方法體內部,與 Step Into 不同的是,會進入JDK的方法;

  • Step Out

    快捷鍵: Shift + F8

    跳出方法體;一般會配合 (Force)Step Into 一起使用

  • Drop frame

    回到方法的呼叫處,同時上下文內所有的變量的值也回到那個時候。

    該按鈕能夠點選的前提條件是: 當前所處的方法有上級方法 ,如果你是main方法裏,那麽按鈕就是灰色,無法點選;

  • Run to Cursor

    快捷鍵: Alt + F9

    將程式碼執行到光標處,光標停在哪裏就執行到哪裏;

  • Evaluate Expression

    快捷鍵: Alt + F8

    運算式小算盤;可執行任意合法的運算式。

  • Trace Current Stream Chain

    追蹤當前Stream流;只有在Stream程式碼上,此按鈕才會亮起。

  • Rerun Main

    快捷鍵: Ctrl + F5

    查詢執行Debug;

  • Resume Program

    快捷鍵: F9

    恢復程式;當因為斷點導致程式碼停止之後,此功能可以讓持續恢復執行;有下一個斷點時,會跳轉到下一個斷點;沒有下一個斷點,會執行到持續結束;

  • Stop Main

    快捷鍵: Ctrl + F12

    停止程式;

  • View Breakpoints

    快捷鍵: Ctrl + Shift + F8

    開啟斷點管理視窗;

  • Mute Breakpoints

    停用所有的斷點;

  • Get Thread Dump

    拿到當前執行緒的Dump,可以檢視當前執行緒的狀態;

  • 篩選

  • 偵錯小技巧

    行斷點

    行斷點的圖示是一個 圓形的紅點,在需要斷點的程式碼行頭點選,即可添加斷點

    方法斷點

    將斷點打在某個具體的方法上,方法執行的時候,會進入斷點;

    舉個方法偵錯最常用的Debug場景:

    當閱讀源碼或者自己寫業務需求的時候,經常會用到策略、樣版方法等設計模式;在偵錯的時候,需要知道,當前介面方法或者抽象方法的執行,到底是走的哪一個具體的實作,用 方法偵錯 就能很方便的找到;如下範例;

    介面 Service 有兩個具體的實作: ServiceA ServiceB ,分別實作了介面的 method 方法,偵錯的過程中就可以將斷點打在介面的method方法上;當我們在Main方法中例項化了ServiceB,斷點就自動進入到ServiceB的method()方法了;

  • 介面Service

    publicinterfaceService{
    voidmethod();
    }

  • ServiceA

    public classServiceAimplementsService{
    @Override
    publicvoidmethod(){
    System.out.println("Service A");
    }
    }

  • ServiceB

    public classServiceBimplementsService{
    @Override
    publicvoidmethod(){
    System.out.println("Service B");
    }
    }

  • Main

    public classMain{
    publicstaticvoidmain(String[] args){
    Service serviceB = new ServiceB();
    serviceB.method();
    }
    }

  • 更多功能點

  • Condition

    用於輸入運算式,進行過濾

  • Watch

    Method entry 和 Method exit 至少有一個選項存在。

  • Emulated

    用於提高偵錯效能

  • Method entry

    進入方法時啟用斷點

  • Method exit

    結束方法時啟用斷點

  • 內容斷點

    在內容的行頭點選即可添加一個小眼睛一樣的內容監聽斷點,用於監聽某個內容的讀寫變化過程;

    更多功能點

  • Condition

    用於輸入運算式,進行過濾

  • Watch

  • Filed Access

    讀取此內容時(寫入時不管)

  • Filed modification

    寫入此內容時(讀取時不管)

  • 異常斷點

    異常斷點是開發、偵錯的時候經常用到的一個功能,用於快速定位到那行程式碼出現了異常;

    設定方式:

  • 第一步,使用快捷鍵 Ctrl + Shift + F8 開啟配置視窗;

  • 第二步,點選左上角的 + 號;

  • 第三步,選擇 Java Exception Breakpoints

  • 第四步,添加需要斷點的異常,如: ArithmeticException

  • 第五步,Debug執行,當出現指定的異常時,就會進入斷點;

  • 更多功能點

  • Condition

    用於輸入運算式,進行過濾

  • Watch

  • Caught excetion

    只有當你自己try-catch了這個異常才會啟用斷點

  • Uncaught excetion

    只有當你自己不try-catch時才會啟用斷點

  • 臨時斷點

    臨時斷點是指 只觸發一次的斷點 ,之後就自動取消了;一般用於特定的場合下需要確認值是符合我們的預期,完了之後就不在需要了;

    設定及演示過程如下:

    設定方式:

  • 第一步,設定斷點

  • 第二步,使用快捷鍵 Ctrl + Shift + F8 開啟配置視窗;

  • 第三步,找到對應的斷點;

  • 第四步,勾選 Remove once hit

  • 第五步,Debug執行,當斷點觸發一次之後,就自動取消了;

  • 斷點條件

    設定斷點的觸發條件,也是閱讀源碼、修復Bug經常用到的一個功能,比如讀Spring源碼,研究Bean生命周期的時候,就可以根據Bean的name去設定斷點條件,用來判斷之後在操作指定物件的時候,才進入斷點;

    如下範例:

    1. for迴圈之後只有i是2的倍數時,才進入斷點,可以在Conditon中填入 i % 2 == 0

    2. 0-10000的迴圈,當i等於5000的時候,進入斷點,其他的時候忽略,可以在Conditon中填入 i == 5000

    設定過程:

  • 第一步,設定斷點

  • 第二步,右鍵斷點處,開啟操作界面

  • 第三步,輸入運算式,比如迴圈時只有偶數才斷點,可以輸入 i % 2 == 0

  • 模擬異常

    開發過程中,有時候需要人為制造一些異常,比如事務操作(@Transactional),需要驗證是否能達到回滾的效果;

    比如下面的虛擬碼:

    // 虛擬碼 假如這裏是個事務操作
    // @Transactional
    publicvoidsave()throws RuntimeException{
    table1Save();
    // 我先在這裏測試一下,異常之後,是否會滾
    //throw new RuntimeException("異常了");
    table2Save();
    table3Save();
    }
    voidtable1Save(){}
    voidtable2Save(){}
    voidtable3Save(){}

    當咱希望在執行 table2Save() 的時候,拋個異常,讓整個操作回滾,通常的做法是會在程式碼中人為拋一個異常:

    thrownew RuntimeException("異常了");

    這樣做並沒有什麽錯,但是不是很優雅,而且還存在一下的兩個問題:

  • 只能在方法的末尾拋異常;流程中間拋,後面的程式碼會報錯

  • 有風險

    這種業務功能中人為拋異常,如果一不小心忘記刪除,將這個異常送出上去,就是人為的生產事故,可能帶來比較嚴重的後果;

  • IDEA優雅模擬異常

    那有沒有什麽更好的方式呢?IDEA給我們提供了更加最佳化的模擬異常方案,不用寫異常程式碼,可以利用工具直接丟擲異常,操作步驟如下:

    操作步驟:

  • 第一步,在要模擬異常的地方加上斷點;

  • 第二步,Debug模式執行程式碼並進入斷點;

  • 第三步,Frames中找到對應的斷點記錄;

  • 第四步,右鍵,選擇 Throw Execption

  • 第五步,輸入你想丟擲的異常,點選 ok ,即可丟擲對應的異常;

  • 多執行緒偵錯

    多執行緒開發的時候,執行緒的排程策略並不由程式碼控制,導致斷點偵錯的過程可能會線上程間跳來跳去,如果邏輯復雜點,跳著跳著可能就蒙蔽了;如下範例:

    public classMain{
    publicstaticvoidmain(String[] args){
    System.out.println("0 main start");
    new Thread(() -> {
    System.out.println("1 hello");
    }, "thread1").start();
    new Thread(() -> {
    System.out.println("2 world");
    }, "thread2").start();
    System.out.println("3 main end");
    }
    }

    如果把斷點打在 System.out.println 上,除了0是能保證第一個輸出的,1、2、3的執行順序是沒辦法保證的;

    預設情況下,斷點的 suspend 設定是 all ,順序並不固定;

    如果將所有斷點的 suspend 設定為 Thread 之後,就會按著執行緒的順序,逐個去執行:

    修改變量

    在斷點的過程中去修改某個變量的值;常見的場景是:當某個變量,因為邏輯bug導致內容值和預期的不一樣,但是又不想從頭再 debug一遍 ,就可以直接在偵錯的過程中修改成預期的值,並繼續執行後續的步驟;

    斷點執行程式碼/方法/運算式

    斷點過程中,可以執行一段運算式、程式碼或者方法

  • 程式碼

  • 方法執行

  • 運算式

  • 遠端偵錯

    非常實用且特別裝B的一個技能,當線上程式碼出現Bug之後,可以透過此方式用本地程式碼進行遠端偵錯,快速定位問題並修復;

    註意: 遠端偵錯必須保證本地程式碼和線上程式碼版本一致,否則不會進入斷點

    設定步驟如下:

  • 添加一個用於遠端偵錯的介面

    @RestController
    public classRemoteDebugController{
    @GetMapping("debug")
    public Integer debug(Integer p){
    System.out.println(p);
    return p;
    }
    }

  • 將程式碼打成jar包

    mvn clean package -Dmaven.test.skip=true

  • IDEA 設定遠端偵錯啟動項

    以下時幾個重要參數的說明

  • Name

    名稱,不重要,隨意填寫;

  • Host

    遠端服務所處的機器IP,這裏是本機測試,所以填寫127.0.0.1即可,實際使用填寫遠端服務所處的真實IP

  • PORT

    遠端偵錯的埠

  • 遠端服務執行時的JVM參數

    IDEA 工具幫我們生成的服務執行時需要添加的JVM參數,直接復制使用即可;

    -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5555

  • 啟動計畫

    為了演示,這裏就不在IDEA中啟動了,直接在CMD視窗下啟動測試計畫, 記得用上上面生成的參數

    java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5555 -jar spring-boot-001-hello-world-0.0.1-SNAPSHOT.jar

    啟動過程出現socket的監聽日誌,說明正常

    Listening for transport dt_socket at address: 5555

  • IDEA 遠端偵錯配置

  • 測試

    左側 為jar包執行的控制台;右 上方為IDEA的界面; 下方為瀏覽器,模擬客戶端請求;

    如下圖示:

    當客戶端發起請求的時候,IDEA就會進入斷點,當執行透過,可以看出,左側控制台就會打印出對應的日誌;

    線上偵錯,務必要給斷點加上條件,比如特定測試帳號才進去斷點;避免讓真是使用者的請求也進入斷點,影響使用者的使用

    透過此方式,如果遠端的程式碼有bug,就可以直接在原生的IDEA工具中進行偵錯,非常的方便;

  • 更多功能

    上面列舉了絕大部份常用的Debug功能,但是這並不是所有的,一些不常用功能可以根據需要選擇使用

    總結,工欲善其事必先利其器,利用好工具,就能做到事半功倍,趕緊收藏,用起來吧!

    好了,今天的分享就到這裏,感謝大家的點贊、轉發、收藏!

    >>

    END

    精品資料,超贊福利,免費領

    微信掃碼/長按辨識 添加【技術交流群

    群內每天分享精品學習資料

    最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎並行JVMMySQLRedisSpringSpringMVCSpringBootSpringCloud訊息佇列等多個型別),歡迎您的使用。

    👇👇

    👇點選"閱讀原文",獲取更多資料(持續更新中