定位Bug技巧總結

解決Bug是編程人員的天職(創造Bug算是一種天賦吧),甚至有人這麼認爲:開發人員的能力可以依據他能決解Bug的複雜程度來評定。簡單的Bug大多數程序員是靠臆斷來解決的,但是當Bug隱藏在代碼的最深處,臆斷不能夠解決問題的時候,或許我們就得依靠些許技巧而不是重啓。

1.打印輸出,在關鍵位置用System.out.print(); 輸出即時參數或者結果(事實上我更贊同用System.err.print(); 因爲那樣你的輸出更明顯),然後來判斷程序的走向是否正確無疑簡單快捷粗暴,程序新手也樂此不疲的使用打印來尋找Bug,但是這種方法缺陷是顯而易見的:要求程序規模不能太大,因爲你很難找到合適的地方,而且往往你也不知道打印出來的參數是什麼意思;不適宜多線程環境下使用,你無法確定打印的順序;要求程序運行最好是簡單有序的,而且Bug是畢現的;線上程序出問題無法及時找到問題,必須在本地加上打印進行調試;

2.打印堆棧,通過在事發地點主動調用 new Exception().printStack(); 幫助程序員瞭解程序的走向。特別是當某個接口被廣泛調用的時候:當程序出錯,你希望找到錯誤的源頭,那麼你就可以通過打印錯誤堆棧來找到始作俑者。

3.臆斷錯誤信息,通過系統打印的錯誤堆棧信息來推測錯誤原因並加以解決。好吧,這裏我實在諷刺大多數不精明的程序員(同時也包括我自己)在看到錯誤信息後,迫不及待的享受解決Bug的快感,並不仔細查看堆棧信息,往往只解決了表面問題而忽略了更深層次問題。因爲在這裏受過的挫折太多了,我不得不舉兩個例子來加以警告:
情景i:《修仙》項目初期,玩家在進行某些位移操作時候服務器會報出空指針異常錯誤,於是我根據錯誤堆棧信息來到了事發地點,並且加上了判空操作並 以爲解決了這個問題,事實上當回過頭來仔細檢查的時候發現這個錯誤是由於底層移動組件的報錯引起的,也就是說如果沒有檢查,我僅僅把表面解決了等同於我吧錯誤隱藏的更深了,看起來表現沒有錯,但是底層在不停的進行錯誤的操作,誰也不知道最後會發生什麼。
情景ii:項目線上運行時,同事拿給我一份錯誤的堆棧信息,是一個ConcurrentModificationException,也就意味着我需要仔細檢查一下我的迭代器,防止元素的意外添加和移除,我簡單的看了下報錯的行數,“那裏”恰好是一個循環,於是我對這個循環做了仔細的深入的檢查,並沒有發現錯誤,於是我決定找同事聊一下,我們一起仔細的看了遍堆棧信息,尷尬的發現我找錯地方了 ,由於本地有部分代碼沒有提交,因此本地的行數和服務日誌記錄的報錯的行數不一致,也就是說我根本沒有仔細的查看錯誤堆棧信息。爲了避免類似的尷尬,請各位務必仔細查看錯誤的堆棧詳情。
此處的所謂臆斷,其實我想說以前的我並不是這樣的,那時候我並不瞭解各個異常的含義,但是我對它們很感興趣,我會仔細閱讀錯誤堆棧信息,找到問題所在,並且試圖發現更深的問題,但不知道什麼時候開始,看到異常堆棧直覺會告訴我這個異常是這麼回事,代表着什麼什麼,一般是由於什麼錯誤操作導致的,然後按照習慣去解決它。雖然根據經驗去推測錯誤本身並沒有錯,但我想作爲程序員,檢查錯誤時的仔細態度是必不可少的。

4.代碼調試, 使用調試工具進行代碼調試,可以說是很通用萬能的查找Bug的手段,可以說是程序員基本功。調試沒有什麼還說的,只能說代碼調試容易上手,但在程序中快速找到合適的地方斷點纔是難點。斷點調試雖然好用,依然有些缺陷:不能用於線上程序;多線程環境會影響到調試的正確性。

5.日誌記錄,通用的做法就是在程序中增加不同級別的日誌記錄。日誌記錄可以說是一種比較全面的尋找和解決Bug方式,根據日誌記錄的異常堆棧信息找出Bug所在並加以解決是一種理想的狀態,當然程序中哪裏加日誌,按什麼格式和形式追加日誌(按照不同緯度,不同視角)都決定了你尋找和解決Bug的輕鬆程度,尤其是在多線程環境中(沒錯,日誌可以用來記錄多線程環境下那些不容易復現的Bug)。記錄日誌很容易,拿Java來說有很多優秀的用來記錄日誌的框架,如Logger4j,Slf4j等,允許使用者定製日誌的格式和形式,但是閱讀日誌卻不是那麼容易。通常一個成熟線上產品的日誌,每天的日誌就可以達到GB級別,每一篇日誌可能也是MB的文檔,在這些日誌中找到你想要的可能需要一些技巧:熟悉程序是很必要的,起碼知道異常模塊的入口和出口;放棄使用鼠標,閱讀日誌時用鼠標滑來滑去絕對不是理智的做法,你應該使用查找來幫助你快速定位錯誤和找到你所需要的,如果你不知道你需要查找些什麼,參考第一點;堆棧信息的時間很重要,一般的日誌都會記錄時間,知道異常發生的時間也許幫助你瞭解很多。
(注:日誌的格式是指記錄日誌的模板,如:時間-線程-類-方法;記錄日誌的形式,如:按天記載,按賬號記載。)

6.使用分析工具,使用Java 提供的分析工具如JMC,Java Visual VM ,可以幫助你分析程序的運行狀況如CPU,內存,線程等,這些工具可以用來定位不易發現的內存泄漏問題以及項目後期的優化。

7.查看API文檔和GOOGLE,查看官方的API文檔可以幫助你更好更快的掌握和使用一個工具類或者框架,記得誰說過:查看官方API文檔可以幫助解決80%開發中遇到的問題,剩餘的20%你都可以GOOGLE到你想要的答案。

8.如果以上方法均不能解決問題,那麼更可能是你把問題想的太複雜,或許應該休息一下。

雖然上面介紹了許多關於定位Bug的方法,但不得不說查找Bug總是費時而且讓人頭大的,爲了避免陷入查找Bug的窘境,請在編寫代碼的時候謹記墨菲定律:任何可能出錯的事情最終都會出錯。這點程序上尤爲明顯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章