1. 程式人生 > >80%的程式設計師都不瞭解的除錯技巧

80%的程式設計師都不瞭解的除錯技巧

本文轉載自公眾號  Tomcat那些事兒

程式設計師的工作內容,除了大部分時間寫程式碼之外,因為有不少的時間是用在除錯程式碼上。甚至說不是在除錯程式碼,就是即將除錯程式碼。 :)

今天我們來談談除錯程式碼的一些技巧,在使用IDE提供的debugger時一些快速定位問題的方式。

看到這裡的朋友,不要馬上認為我標題黨,再往下看看,如果你還有一些更好用的技巧,歡迎留言。

下面進入正題。

1 多執行緒除錯

開發過多執行緒應用的朋友應該有體會,有些時候,為了觀察多個執行緒間變數的不同狀態,以及鎖的獲取等,就會想到在程式碼里加個斷點debug一下。

在IDE裡斷點停下來的時候,可以切換到另外的執行緒中,跑其他的程式碼,不會互相影響。當然,這裡是有個開關的,在Eclipse裡預設開啟,

但是在IntelliJ IDEA裡預設是沒有開啟的。也就是說如果你在IDEA裡程式碼里加斷點,雖然一個執行緒的斷了下來,但其他執行緒的已經執行過了。此處把執行緒的suspend設定成和Eclipse模式一樣之後,也可以開始多執行緒應用的除錯。簡單設定可以直接在斷點處,將suspend改成Thread

一個執行緒斷下來之後,可以通過線上程視窗切換,到其它執行緒中繼續執行。

IntelliJ IDEA裡在這兒切換

我們看到main執行緒和pool-1-thread-1這兩個執行緒都處於RUNNING狀態,切換到任何一個都可以繼續執行。

此時,就可以寫一個多執行緒的應用,同時向ArryList這一類非執行緒安全的容器中存放內容,然後觀察為什麼他們是執行緒不安全的,會出現什麼問題,生動又形象。

PS: 這裡順道說一下,這就是為什麼建立執行緒時建議起一個有意義的名字,至少是可以識別的名字,否則在這裡都不能區分出哪個是自己的執行緒,想切換還麻煩。

2 後退執行

這裡所說的後退執行,是有些時候我們在debug程式碼時,懶的每個方法都進入單步除錯,就會出現你觀察一個變數值的變化時,某個方法沒跟進去,結果值就變了,不得不重來一次

依靠後退執行的功能,可以後退,就像下棋時悔棋那種功能一樣。當然,這個後退招待的名字是我自己起的,在IDE裡被稱為Drop Frame

有了這個功能,我們在Drop 了當前這個Frame之後,已經改變的變數值不會恢復。比如你向當前呼叫方法裡傳入了一個List,並且在方法中向List裡添加了內容,那在Drop到呼叫該方法的地方時,List不會恢復到之前的狀態。

但是在該方法再次被呼叫時,你可以觀察List什麼時候被改變的,至少不需要再重跑一遍程式了。甚至你可以一言不合就後退。

3 條件斷點

為了除錯程式碼,就需要在要觀察變更的地方新增斷點,然後小心翼翼的一步步執行。但是如果是在一個迴圈裡,又或者該方法會被多執行緒同時呼叫到的時候,你小心的向下單步除錯,發現沒有你關心的內容,又從迴圈開始處跑下來,還是沒你的內容,人就開始煩燥起來。

其實,在新增斷點的時候,我們可以為斷點增加一定的條件,這樣,在指定的條件滿足時,斷點才會生效。

IntelliJ IDEA內,在斷點上右擊,會彈出如下圖的條件框,輸入指定的條件即可。

有了條件斷點,不相關,不感興趣的程式碼就可以直接跳過了。

4 片斷程式碼

這個沒想好用什麼名字來表述。有些時候在除錯過程中,忽然想招待一段與此相關,但不在原始檔中的程式碼來觀察一下,輔助進行問題分析。此時你會停止程式,新增程式碼然後重新跑一次嗎?

在IDEA裡有一個執行程式碼片斷的功能,可以在當前程式碼的上下文內,執行你臨時寫的程式碼。

例如,當前方法傳入一個List,但這個方法裡少一個你後面條件需要使用到的元素,此時你可以臨時使用片斷程式碼執行的功能,新增一個進去。

注意,在IntelliJ IDEA裡,這個上面紅框,像個小計算器的按鈕就是臨時執行的功能,點選之後,會彈出按鈕下方這個Evaluate Expression的框,輸入程式碼,點選右下角的Evalute即可。返回值會顯示在Result處。

這就就相當於臨時改變了變數內容。

然後,還可以呼叫物件的方法,執行功能,獲取屬性值等。

5 檢視變數修改值

每個IDE在除錯程式碼時都提供了一個觀察當前上下文變數值的視窗。其實除了檢視之外,一些非final的基本型別,還可以直接在此處修改值。這樣如果多次迴圈執行時,每次可以恢復到期望的值,不需要重啟程式。