天天看點

【IDEA】IDEA的進階Debug技巧

目錄

    • Debug界面
      • 基本用法&快捷鍵
    • 檢視所有斷點
    • 智能步入
    • 中斷Debug
    • 條件斷點
    • 多線程調試
    • 回退方法
    • 臨時執行表達式/修改變量值
    • 并行啟動項目
  • Debug用來追蹤代碼的運作流程,通常在程式運作過程中出現異常,啟用Debug模式可以分析定位異常發生的位置,以及在運作過程中參數的變化。
  • 通常我們也可以啟用Debug模式來跟蹤代碼的運作流程去學習三方架構的源碼。

Debug界面

首先看下IDEA中Debug模式下的界面。

如下是在IDEA中啟動Debug模式,進入斷點後的界面,我這裡是Windows,可能和Mac的圖示等會有些不一樣。就簡單說下圖中标注的8個地方:

【IDEA】IDEA的進階Debug技巧
  1. 以Debug模式啟動服務,左邊的一個按鈕則是以Run模式啟動。在開發中,我一般會直接啟動Debug模式,友善随時調試代碼。
  2. 斷點:在左邊行号欄單擊左鍵,或者**

    快捷鍵Ctrl+F8 打上/取消斷點

    **,斷點行的顔色可自己去設定。
  3. Debug視窗:通路請求到達第一個斷點後,會自動激活Debug視窗。如果沒有自動激活,可以去設定裡設定
  4. 調試按鈕:一共有8個按鈕,調試的主要功能就對應着這幾個按鈕,滑鼠懸停在按鈕上可以檢視對應的快捷鍵。在菜單欄Run裡可以找到同樣的對應的功能,
  5. 服務按鈕:可以在這裡關閉/啟動服務,設定斷點,禁用斷點,檢視所有斷點等。
  6. 方法調用棧:這裡顯示了該線程調試所經過的所有方法,勾選右上角的[Show All Frames]按鈕,就不會顯示其它類庫的方法了,否則這裡會有一大堆的方法。
  7. Variables:在變量區可以檢視目前斷點之前的目前方法内的變量。
  8. Watches:檢視變量,可以将Variables區中的變量拖到Watches中檢視

在設定裡勾選Show debug window on breakpoint,則代碼執行到到斷點後自動激活Debug視窗

【IDEA】IDEA的進階Debug技巧

如果你的IDEA底部沒有顯示工具欄或狀态欄,可以在View裡打開,顯示出工具欄會友善我們使用。可以自己去嘗試下這四個選項

【IDEA】IDEA的進階Debug技巧

在菜單欄Run裡有調試對應的功能,同時可以檢視對應的快捷鍵。

【IDEA】IDEA的進階Debug技巧

基本用法&快捷鍵

首先說第一組按鈕,共8個按鈕,從左到右依次如下

【IDEA】IDEA的進階Debug技巧

Show Execution Point (Alt + F10):如果你的光标在其它行或其它頁面,點選這個按鈕可跳轉到目前代碼執行的行。

Step Over (F8):步過,一行一行地往下走,如果這一行上有方法不會進入方法。

Step Into (F7):步入,如果目前行有方法,可以進入方法内部,一般用于進入自定義方法内,不會進入官方類庫的方法,如第25行的put方法。

Force Step Into (Alt + Shift + F7):強制步入,能進入任何方法,檢視底層源碼的時候可以用這個進入官方類庫的方法。

Step Out (Shift + F8):步出,從步入的方法内退出到方法調用處,此時方法已執行完畢,隻是還沒有完成指派。

Drop Frame (預設無):回退斷點

Run to Cursor (Alt + F9):運作到光标處,你可以将光标定位到你需要檢視的那一行,然後使用這個功能,代碼會運作至光标行,而不需要打斷點。

Evaluate Expression (Alt + F8):計算表達式

Resume Program (F9):,恢複程式運作,但是如果該斷點下面代碼還有斷點則停在下一個斷點上

第二組按鈕,共7個按鈕,從上到下依次如下

【IDEA】IDEA的進階Debug技巧

Rerun ‘xxxx’:重新運作程式,會關閉服務後重新啟動程式。

Update ‘tech’ application (Ctrl + F5):更新程式,一般在你的代碼有改動後可執行這個功能。而這個功能對應的操作則是在服務配置裡,如圖2.3。

Resume Program (F9):恢複程式,假設:在第20行和25行有兩個斷點,目前運作至第20行,按F9,則運作到下一個斷點(即第25行),再按F9,則運作完整個流程,因為後面已經沒有斷點了。

Pause Program:暫停程式,啟用Debug。目前沒發現具體用法。

Stop ‘xxx’ (Ctrl + F2):連續按兩下,關閉程式。有時候你會發現關閉服務再啟動時,報端口被占用,這是因為沒完全關閉服務的原因,你就需要清除所有JVM程序了。

View Breakpoints (Ctrl + Shift + F8):檢視所有斷點

Mute Breakpoints: 啞的斷點,選擇這個後,所有斷點變為灰色,斷點失效,按F9則可以直接運作完程式。再次點選,斷點變為紅色,有效。如果隻想使某一個斷點失效,可以在斷點上右鍵取消Enabled

變量檢視

  1. 在IDEA中,參數所在行後面會顯示目前變量的值
    【IDEA】IDEA的進階Debug技巧
  2. 光标懸停到參數上,顯示目前變量資訊
    【IDEA】IDEA的進階Debug技巧
  3. 在Variables裡檢視,這裡顯示目前方法裡的所有變量
    【IDEA】IDEA的進階Debug技巧
  4. 4、在Watches裡,點選New Watch,輸入需要檢視的變量。或者可以從Variables裡拖到Watche裡檢視
    【IDEA】IDEA的進階Debug技巧
    如果你發現你沒有Watches,點選重置布局
    【IDEA】IDEA的進階Debug技巧

檢視所有斷點

點選View Breakpoints (Ctrl + Shift + F8),檢視所有斷點。

  • Java Method Breakpoints
  • Java Field Watchpoints
  • Java Exception Breakpoints
  • JavaScript Exception Breakpoints
    【IDEA】IDEA的進階Debug技巧

Java Line Breakpoints

左邊

顯示了所有的斷點,在

右邊勾選Condition

,可以設定斷點的條件。

  • 勾選Log message to console,則會将目前斷點行輸出到控制台
  • 勾選Evaluate and log,可以在執行這行代碼是計算表達式的值,并将結果輸出到控制台。
    【IDEA】IDEA的進階Debug技巧

右邊的Filters過濾

, 這些一般情況下不常用,簡單說下意思

  • Instance filters:執行個體過濾,輸入執行個體ID,但是我這裡沒有成功,不知道什麼原因,知道的朋友留個言。
  • Class filters:類過濾,根據類名過濾,同樣沒有成功….
  • Pass count:用于循環中,如果斷點在循環中,可以設定該值,循環多少次後停在斷點處,之後的循環都會停在斷點處。
    【IDEA】IDEA的進階Debug技巧

異常斷點

: 通過設定異常斷點,在程式中出現需要攔截的異常時,會自動定位到異常行。

  • 點選**+号添加Java Exception Breakpoints**,添加異常斷點。然後輸入需要斷點的異常類,之後

    可以在Java Exception Breakpoints裡看到添加的異常斷點。

    【IDEA】IDEA的進階Debug技巧
    【IDEA】IDEA的進階Debug技巧
    如: 添加了一個

    NullPointerException異常斷點

    ,出現空指針異常後,自動定位在空指針異常行。
    【IDEA】IDEA的進階Debug技巧

智能步入

一行代碼裡有好幾個方法,怎麼隻選擇某一個方法進入。之前提到過使用Step Into (Alt + F7) 或者 Force Step Into (Alt + Shift + F7) 進入到方法内部,但這兩個操作會根據方法調用順序依次進入,這比較麻煩。

那麼智能步入就很友善了,智能步入,這個功能在Run裡可以看到,Smart Step Into (Shift + F7),如圖

【IDEA】IDEA的進階Debug技巧

按Shift + F7會自動定位到目前斷點行,并列出需要進入的方法,點選方法進入方法内部。

如果隻有一個方法,則直接進入,類似Force Step Into(Alt + Shift + F7)。

【IDEA】IDEA的進階Debug技巧

中斷Debug

想要在Debug的時候,中斷請求,不要再走剩餘的流程了?

有些時候,我們看到傳入的參數有誤後,不想走後面的流程了,怎麼中斷這次請求呢(後面的流程要删除資料庫資料呢….),難道要關閉服務重新啟動程式?嗯,我以前也是這麼幹的。

确切的說,我也沒發現可以直接中斷請求的方式(除了關閉服務),但可以通過Force Return,即強制傳回方法傳回值來避免後續的流程

點選Force Return,彈出Return Value的視窗,我這個方法的傳回類型為INT,是以,我這裡設定目前方法傳回200,來強制傳回,進而不再走方法後面代碼。

【IDEA】IDEA的進階Debug技巧
【IDEA】IDEA的進階Debug技巧
【IDEA】IDEA的進階Debug技巧

條件斷點

條件斷點可以對指定斷點設定條件,隻有

目前斷點行滿足條件

才會進入debug模式

代碼如下:

@Test
public void conditionDebug() {
    for (int i = 0; i < 30; i++) {
        System.out.println(i);
    }
}
           

使用條件斷點步驟

  1. 滑鼠左鍵在行數上加上斷點
  2. 在斷點上右鍵加上條件表達式
  3. 點選Done按鈕
    【IDEA】IDEA的進階Debug技巧
    此時斷點上會有問号,表示這是一個條件斷點,右鍵點選即可檢視條件

運作程式,i==20才會進入debug

【IDEA】IDEA的進階Debug技巧

多線程調試

當有多個線程時,我們如何控制線程的執行順序呢?

代碼如下:

@Test
    public void thread() {
        System.out.println("主線程開始");
        new Thread(() -> {
            System.out.println("我是線程1-1");
            System.out.println("我是線程1-2");
            System.out.println("我是線程1-3");
        }, "線程1").start();

        new Thread(() -> {
            System.out.println("我是線程2-1");
            System.out.println("我是線程2-2");
            System.out.println("我是線程2-3");
        }, "線程2").start();

        System.out.println("主線程開始結束");
    }
           

普通模式debug模式下是做不到的,因為我們沒辦法控制線程的執行順序。需要做如下設定

  1. 滑鼠左鍵在行數上加上斷點
    【IDEA】IDEA的進階Debug技巧
  2. 滑鼠右鍵打開斷點配置,選中Thread選項後,點選 mark default(

    有就設定

    ),然後點選 Done儲存
    【IDEA】IDEA的進階Debug技巧
    設定後的斷點如下,3個斷點都是Thread模式
    【IDEA】IDEA的進階Debug技巧
  3. 啟動項目,控制指定線程輸出内容

執行到某個語句想切換線程的時候選中下拉框中下一步要執行的線程即可

  • Frames的下拉清單裡,可以切換目前的線程,如下我這裡有兩個Debug的線程,切換另外一個則進入另一個Debug的線程。
    【IDEA】IDEA的進階Debug技巧

先輸出線程1

System.out.println(“我是線程1-1”);

System.out.println(“我是線程1-2”);

在輸出線程2

System.out.println(“我是線程2-1”);

System.out.println(“我是線程2-2”);

然後輸出線程1

System.out.println(“我是線程1-3”);

然後接着輸出線程2

System.out.println(“我是線程2-3”);

最後輸出主線程

System.out.println(“主線程結束”);
【IDEA】IDEA的進階Debug技巧

回退方法

代碼如下:

/**
     * 回到上一個斷點
     */
    @Test
    public void back() {
        int num = 10;
        method1(num);
    }

    public void method1(int num) {
        num += 10;
        method2(num);
    }

    public void method2(int num) {
        num += 10;
        System.out.println(111);
        System.out.println(222);
        System.out.println(333);
        System.out.println(444);
        System.out.println(555);
    }
           
【IDEA】IDEA的進階Debug技巧

當斷點執行到method2()時,想回退到method1時,點選如下按鈕即可

【IDEA】IDEA的進階Debug技巧

點完之後

【IDEA】IDEA的進階Debug技巧
  • 所謂的斷點回退,其實就是回退到上一個方法調用的開始處,在IDEA裡測試無法一行一行地回退或回到到上一個斷點處,而是回到上一個方法。

回退的方式有兩種,

  • 一是Drop Frame,按調用的方法逐漸回退,包括三方類庫的其它方法(取消Show All Frames按鈕會顯示三方類庫的方法
    【IDEA】IDEA的進階Debug技巧

二是在調用棧方法上選擇要回退的方法,右鍵選擇Drop Frame,回退到該方法的上一個方法調用處,此時再按F9(Resume Program),可以看到程式進入到該方法的斷點處了。

【IDEA】IDEA的進階Debug技巧
但有一點需要注意,斷點回退隻能重新走一下流程,之前的某些參數/資料的狀态已經改變了的是無法回退到之前的狀态的,如對象、集合、更新了資料庫資料等等。

臨時執行表達式/修改變量值

public class User {

	private String username;
	private Integer age;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
}

@Test
public void changeValue() {
	User user = new User();
	user.setUsername("aa");
	System.out.println(user.getUsername() + " " + user.getAge());
}
           

進入斷點模式後選中Variables,将目前代碼行的某個參數Add to Watches 到 Watcher中

【IDEA】IDEA的進階Debug技巧

按F2然後調用user.setAge()方法設定age的值為100

  • 設定變量,在計算表達式的框裡,可以改變變量的值,這樣有時候就能很友善我們去調試各種值的情況
【IDEA】IDEA的進階Debug技巧

按F2然後寫檢視user.getName()的長度的表達式

  • 條件表達式不僅可以是一般變量或參數,也可以是方法,當你的一行代碼中調用了幾個方法時,就可以通過這種方式檢視檢視某個方法的傳回值
【IDEA】IDEA的進階Debug技巧

直接Evaluate Expression (Alt + F8)這樣也可以編寫臨時表達式

【IDEA】IDEA的進階Debug技巧

還可以直接右鍵選中Set Value修改userName屬性值等

【IDEA】IDEA的進階Debug技巧
【IDEA】IDEA的進階Debug技巧

并行啟動項目

測試分布式項目時,經常要一個項目啟動2次,不用将一個項目打開多次啟動,配置一下即可

  1. 點選

    Edit Configurations

    【IDEA】IDEA的進階Debug技巧
  2. 勾選Allow parallel run,然後重新啟動項目
    【IDEA】IDEA的進階Debug技巧
    【IDEA】IDEA的進階Debug技巧
  3. 依次修改

    -Dserver.port=指定的端口

    ,然後儲存配置重新啟動項目
【IDEA】IDEA的進階Debug技巧
【IDEA】IDEA的進階Debug技巧

這裡啟動的項目端口為10086/10087

【IDEA】IDEA的進階Debug技巧