程式員的工作内容,除了大部分時間寫代碼之外,因為有不少的時間是用在調試代碼上。甚至說不是在調試代碼,就是即将調試代碼。 :)
今天我們來談談調試代碼的一些技巧,在使用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的基本類型,還可以直接在此處修改值。這樣如果多次循環執行時,每次可以恢複到期望的值,不需要重新開機程式。
原文釋出時間為:2018-07-10
本文作者:侯樹成
本文來自雲栖社群合作夥伴“
程式員小灰”,了解相關資訊可以關注“
”