【IT168 專稿】調(diào)試的方法雖然千千萬萬,但歸根結(jié)底,就是找到引發(fā)錯誤的代碼。Eclipse調(diào)試器的目標是讓程序員能對本地或遠程程序進行錯誤偵測與診斷。該調(diào)試器提供所有標準調(diào)試功能,包括進行單步執(zhí)行、設(shè)置斷點和值、檢查變量和值以及暫掛和恢復線程的能力。這篇文章主要講述Eclipse調(diào)試器,包括Debug視圖,斷點的設(shè)置,Java代碼的調(diào)試等等。與一些理論性較強的文章相比,本文更注重實踐,為讀者提供更加使用的調(diào)試技巧。
Eclipse 調(diào)試器
Eclipse 平臺的最大特色是插件化(Plugin)。調(diào)試是任何程序員都無法回避的工作。因此Eclipse的內(nèi)置插件Java開發(fā)工具包(Java Development Toolkit,簡稱JDT)中集成了一個功能強大的Java調(diào)試器(Debugger)。實際上,JDT是Eclipse工作平臺(Eclipse Platform Workbench)的基礎(chǔ)工具,除了調(diào)試器,還提供透視圖、視圖、編輯器、搜索等Eclipse基礎(chǔ)功能。
由于Eclipse調(diào)試器采用了基于客戶端/服務(wù)器的設(shè)計模式,遠程應(yīng)用的調(diào)試變得與本地一樣簡單。其工作原理是,本地Eclipse工作平臺充當調(diào)試的客戶端,而遠程應(yīng)用所在的機器則充當了調(diào)試服務(wù)器的角色。
Debug 視圖
Debug視圖作為Eclipse調(diào)試器透視圖的一部分,管理與程序調(diào)試相關(guān)的功能。如圖所示,Debug視圖呈樹狀結(jié)構(gòu),每一個線程對應(yīng)一樹節(jié)點。圖中顯示的是暫掛線程Main的調(diào)試堆棧幀結(jié)構(gòu)。
作為標準的Java調(diào)試平臺,Debug視圖提供了許多執(zhí)行控制命令(Execution Control Commands),用于在程序中設(shè)置/取消斷點,單步執(zhí)行,暫掛與恢復線程。以下是一些常用的執(zhí)行控制命令:
1. Layout布局
Debug視圖的布局與斷點調(diào)試等主體功能相比,顯得并不那么乍眼,因此也常被人忽略,不過Eclipse的魅力之一就是它的細節(jié)做的特別完美。我們簡單介紹一下Debug視圖布局的特點,如圖所示。
第一個特點是Automatic功能。選擇菜單選項Layout -> Automatic,可以實現(xiàn)Debug視圖在樹狀模式與Breadrumb模式之間的自動互換。相信很多編程人員都喜歡Breadrumb模式,向面包片一樣,一層一層的,直觀,醒目。
Layout菜單的第二個特點Breadrumb模式。選擇菜單選項Layout -> Breadcrumb,打開Breadrumb模式。除此之外,選擇菜單選項Layout -> Auto-Expand Breadcrumb,可實現(xiàn)自動展開Breadrumb模式。當選擇下拉框時,可自動定位到暫掛線程的調(diào)試堆棧幀。這個細節(jié)對于編程人員來說,也是非常的方便。
2. 調(diào)試啟動停止等相關(guān)命令
Debug視圖提供了諸多的啟??刂泼?,叫法上與其它的調(diào)試器可能稍微有些不同,具體如下:
啟動調(diào)試視圖:Eclipse提供三種方式來啟動程序(Launch)的調(diào)試,分別是通過菜單(Run –> Debug)、圖標(“綠色臭蟲”)以及快捷鍵(F11),在這一點上,與其他命令(例如Run)類似。
停止調(diào)試:Eclipse通過Terminate命令終止對本地程序的調(diào)試。特別的,對于遠程程序的調(diào)試,Eclipse使用Disconnect命令來終止與遠程JVM的socket連接。前面我們談到,Eclipse調(diào)試器采用了基于客戶端/服務(wù)器的設(shè)計模式,本地Eclipse工作平臺充當調(diào)試的客戶端,而遠程應(yīng)用所在的JVM則充當了調(diào)試服務(wù)器的角色。簡單的說,Terminate命令終止本地調(diào)試,Disconnect命令終止遠程調(diào)試。Terminate/Disconnect All終止所有的調(diào)試,包括本地與遠程。
重新啟動調(diào)試:Eclipse通過Relaunch命令重新啟動調(diào)試。這里需要指出的是Relaunch支持兩種重啟動模式,一種是針對已經(jīng)停止的程序調(diào)試,另一種是針對Active的當程序調(diào)試。前者不難理解,效果上等同于Terminate+Launch。后者的處理方式有些不同,效果上則等同于Launch一個新的Debug項。實際上,針對后一種情況,我們通常采用Eclipse的Terminate and Relaunch命令來達到重啟Debug的目的。
刪除調(diào)試項:Eclipse支持針對多個程序的調(diào)試。我們稱每一項對應(yīng)一個Debug Item。Remove命令將某一個Debug Item從當前的Debug視圖中刪除。不過,Remove命令只適用于已停止的Debug Item,而對于運行中的Debug Item,Eclipse提供了Terminate and Remove命令。假如想停止并清除所有的Debug Item,則可以通過Terminate and Remove All命令。此外,Eclipse還提供了Copy Stack命令或者快捷鍵Ctr+C,可將調(diào)試堆棧幀內(nèi)容拷貝至剪貼板中,這樣效果上就等同于“撤銷”。
以上這些命令雖然有些瑣碎,但是非常能反映Eclipse對細節(jié)的把握與控制。
3. 單步執(zhí)行
相信任何調(diào)試人員對單步調(diào)試非常的熟悉。Eclipse提供step into、step over、 step return三個命令來支持單步調(diào)試。三者的具體區(qū)別是:step into(快捷鍵F5)就是單步執(zhí)行,遇到子函數(shù)就進入并且繼續(xù)單步執(zhí)行;step over(快捷鍵F6)是在單步執(zhí)行時,在函數(shù)內(nèi)遇到子函數(shù)時不會進入子函數(shù)內(nèi)單步執(zhí)行,而是將子函數(shù)整個執(zhí)行完再停止,也就是把子函數(shù)整個作為一步。step return(快捷鍵F7)就是單步執(zhí)行到子函數(shù)內(nèi)時,用step return就可以執(zhí)行完子函數(shù)余下部分,并返回到上一層函數(shù)。說的通俗點就是,step into:進入子函數(shù),step over:越過子函數(shù),但子函數(shù)會執(zhí)行,step return:跳出子函數(shù)。
此外,Eclipse還提供了Run to line(快捷鍵Ctr + R)功能,從開始處運行程序,到正在執(zhí)行的斷點暫停。
4. Drop to Frame
Drop to Frame功能雖然不屬于單步調(diào)試的核心,但是該功能非常的適用,它為調(diào)試人員提供了調(diào)試回退的機會。Drop to Frame可以重新跳到當前方法的開始處重新執(zhí)行,并且所有上下文變量的值也相應(yīng)回到初始時刻,如圖所示。
5. Step Filters
當在你調(diào)試的時候,你只希望查看自己的代碼,而不是從JDK或者是其他庫中的代碼,甚至是你也想屏蔽自己代碼庫中的框架部分代碼。
針對這樣的需求,Eclipse提供了逐步過濾器(Step Filters)選項指的是一直執(zhí)行直到遇到未經(jīng)過濾的位置或斷點。Step Filters功能由Use Step Filters,Edit Step Filters,F(xiàn)ilter Type,F(xiàn)ilter Package四項組成。
具體操作如下:
步驟 1: Windows -> Preferences -> Java -> Debug -> Step Filtering.
步驟 2:選擇‘Use Step Filters’.
步驟 3:在屏幕上選中所需的選項。你可以添加你自己代碼庫中的部分代碼。
步驟 4:點擊‘Apply’.
原理上,Edit Step Filter命令用于配置Step Filter規(guī)則,而Filter Type與Filter Package分別指的是過濾的Java類型與Java Package,如圖所示。
6. 聲明選項
Open Declared Type命令會打開當前調(diào)試堆棧幀的類型聲明編輯器。而Open Declared Type Hierarchy則展現(xiàn)的是完整的層次結(jié)構(gòu),如圖所示。
7. 線程的暫掛/恢復
Eclipse通過Suspend與Resume來支持線程的暫掛與恢復。一般來講,Suspend適用于多線程程序的調(diào)試,當需要查看某一個線程的堆棧幀及變量值時,我們可以通過Suspend命令將該線程暫掛。Resume用于恢復。有兩種Resume需要注意:第一是當在調(diào)試過程中修改程序代碼,然后保存,點擊Resume,此時程序會暫掛于斷點。第二是當程序拋出異常時,運行Resume,程序也會暫掛于斷點。
8. Show Monitor命令
Show Monitor命令可實時顯示變量的值。舉個例子,我們寫一個簡單的HelloWorld程序。
/**
* Hello World
*/
如圖所示,Show Monitor對應(yīng)的監(jiān)視信息會以“鑰匙”的形式出現(xiàn)在當前stack frame前面。當前信號量的id為16。
需要指出的是,不是所有的JVM都支持Show Monitor功能。如果是IBM或者是Oracle的JVM,則要求版本高于1.4,否則提示的是Alert信息:VM does not provide monitor information,如圖所示。
調(diào)試選項配置
在調(diào)試程序之前,需要預(yù)先完整地編譯和運行代碼,創(chuàng)建運行配置并確認其正常啟動。舉個例子,假設(shè)我們需要調(diào)試一個HelloWorld的Java Application程序。我們需要如下步驟:
1. 選擇菜單 Run --> Open Run Dialog ,打開Run對話框。在對話框左側(cè)的類型列表中選中Java Application,右鍵 --> New ,新建一個Java Application運行配置HelloWorld,如下圖所示。
根據(jù)目標程序的類型,Eclipse提供了如下幾種類型調(diào)試。Eclipse Application主要針對Eclipse插件本身的調(diào)試,Java Applet針對Java瀏覽器小程序的調(diào)試,Java Application針對Main函數(shù)為如何的Java應(yīng)用程序,JUnit/JUnit Plug-in Test針對的是基于JUnit框架的單元測試程序的調(diào)試,OSGi Framework針對的是基于OSGi框架的程序調(diào)試,所謂OSGi 框架指的是提供一個安全的可管理的Java Framework來部署可擴展的Java服務(wù)。而Remote Java Application針對的是遠程應(yīng)用程序的調(diào)試。
2. 配置項目和啟動類。在運行配置HelloWorld的Main Tab頁,指定Project為導入的Test項目,啟動類為HelloWorld,如下圖所示。其中Main class提供了一個選項,即過濾系統(tǒng)庫中的Main函數(shù)。
3. 在運行配置HelloWorld的Arguments Tab頁配置系統(tǒng)屬性、類加載路徑和工作目錄。Argument分兩部分,即Program arguments與VM argument。Program arguments指的是程序所需的參數(shù),由main函數(shù)的args[]參數(shù)傳入至程序。VM Arguments是設(shè)置虛擬機的屬性。假設(shè)我們對Test類設(shè)置的Program arguments為pro1 pro2 pro3,而VM arguments設(shè)置為-DsysProp1=sp1 -DsysProp2=sp2。那么當點擊Run按鈕運行Java Application,完整的命令應(yīng)該為java -DsysProp1=sp1 -DsysProp2=sp2 Test pro1 pro2 pro3。這里我們不需要指定任何參數(shù)。保留空白。
4. 選擇JRE Tab。Eclipse提供了三種Java運行時選項。分別為Project JRE,Execution enviroment, Alertnate JRE。我們選的是第三種,版本為JDK1.6。
5. Classpath Tab配置類加載路徑。類路徑可以連接 Java 運行庫和文件系統(tǒng)。它定義編譯器和解釋器應(yīng)該在何處查找要加載的 .class 文件。它的基本思想是:文件系統(tǒng)的層次結(jié)構(gòu)反映了 Java 包的層次結(jié)構(gòu),而類路徑則定義了文件系統(tǒng)中的哪個目錄可以作為 Java 包層次結(jié)構(gòu)的根。這里我們采取默認方式。
6. 在Source Tab配置源文件查看路徑。通過右邊的Add按鈕可以從許多地方(包括文件系統(tǒng)、既存項目等)添加源文件查看路徑項。如果我們在調(diào)試需要深入到JDK中,可以通過該Tab添加源代碼。這里配置我們采取默認方式。
7. Environment Tab設(shè)置環(huán)境變量。我們采取默認方式。
8. Common Tab設(shè)置常見的選項,如編碼等。
調(diào)試Java
毫無疑問,最常見的調(diào)試過程就是設(shè)置斷點,以允許檢查在條件語句和循環(huán)中的變量和值。要在 Java 透視圖的 Package Explorer 視圖中設(shè)置斷點,雙擊所選的源代碼文件,在編輯器中打開它。遍歷全部代碼,將光標放置在含有可疑代碼的那一行的標記欄上(在編輯器區(qū)域的左側(cè))。雙擊以設(shè)置斷點。
斷點類型
Breakpoints視圖列出當前工作區(qū)別設(shè)置的所有斷點,如圖所示。按照功能分又可分為:
Java Class Load Breakpoints:當load指定的class時發(fā)生。這個在調(diào)試class load非常有用。
Java Exception Breakpoints:當發(fā)生異常時發(fā)生暫掛。如圖,Choose an exception支持占位符*與?。占位符*表示任何字符串,?表示任意一個字符??梢愿鶕?jù)需要決定在出現(xiàn)異常的時候是否暫掛當前線程。
Java Line Breakpoints:Java行斷點。這是最普通的斷點形式。即雙擊程序中某一行最左邊區(qū)域,添加一個行斷點。
Java Method Breakpoints:Java方法斷點。方法斷點就是將斷點打在方法的入口處,如下圖。方法斷點的特別之處在于它可以打在 JDK的源碼里,由于 JDK 在編譯時去掉了調(diào)試信息,所以普通斷點是不能打到里面的,但是方法斷點卻可以,可以通過這種方法查看方法的調(diào)用棧。
Java Watch Breakpoints:Java變量監(jiān)視斷點,實時地監(jiān)視變量的變化
斷點屬性
Hit count:選擇breakpoint view->右鍵hit count。設(shè)置執(zhí)行次數(shù),適合調(diào)試程序中的for循環(huán)。當循環(huán)中達到指定次數(shù),則暫掛該線程或者虛擬機本身。
條件斷點:斷點大家都比較熟悉,在Eclipse Java 編輯區(qū)的行頭雙擊就會得到一個斷點,代碼會運行到此處時停止。條件斷點,顧名思義就是一個有一定條件的斷點,只有滿足了用戶設(shè)置的條件,代碼才會在運行到斷點處時停止。在斷點處點擊鼠標右鍵,選擇最后一個"Breakpoint Properties"。條件斷點的條件一般來說有兩種類型,一種是boolean變量為真,另一種是當偵測到變量值改變。
斷點的導入與導出:這這對于調(diào)試大型工程非常有幫助。既可以導入導出所有的斷點,也可以加以選擇。導出文件的后綴為.bkpt。
變量屬性
查看變量:Variables 視圖(在 Display 窗口中)顯示了選中的堆棧幀中的變量值。要查看所請求的變量,只需展開 Variables 視圖中的樹直到所請求的元素為止。
改變變量值:Variables 視圖不僅能查看變量,而且能夠改變變量的值。如果您也碰到下面的問題,建議使用改變量值。即當代碼停在了斷點處,但是傳過來的值不正確,如何修改一下變量值保證代碼繼續(xù)走正確的流程,或是說有一個異常分支老是進不去,能不能調(diào)試時改一下條件,看一下異常分支代碼是否正確?
表達式屬性
要在 Debug 透視圖的編輯器中求表達式的值,選中設(shè)置有斷點的一整行,并在上下文菜單中選擇 Inspect 選項。表達式是在當前堆棧幀的上下文中求值的,其結(jié)果顯示在 Display 窗口的 Expressions 視圖中。
Eclipse 提供了內(nèi)置的 Java 調(diào)試器,具有標準調(diào)試功能,包括進行單步執(zhí)行、設(shè)置斷點和值、檢查變量和值、暫掛和恢復線程的能力。Eclipse同時也是一個可支持許多其它語言的可擴展平臺,而其中最重要的就是支持 C/C++。Eclispe官方網(wǎng)站:http://www.eclipse.org
聯(lián)系客服