在本地計(jì)算機(jī)上調(diào)試 Java™ 應(yīng)用程序并不是惟一的選擇。學(xué)習(xí)如何使用構(gòu)成遠(yuǎn)程調(diào)試的不同連接類型進(jìn)行遠(yuǎn)程調(diào)試。本文概述了設(shè)置遠(yuǎn)程應(yīng)用程序調(diào)試的特性和示例。
遠(yuǎn)程調(diào)試對(duì)應(yīng)用程序開發(fā)十分有用。例如,為不能托管開發(fā)平臺(tái)的低端機(jī)器開發(fā)程序,或在專用的機(jī)器上(比如服務(wù)不能中斷的 Web 服務(wù)器)調(diào)試程序。其他情況包括:運(yùn)行在內(nèi)存小或 CUP 性能低的設(shè)備上的 Java 應(yīng)用程序(比如移動(dòng)設(shè)備),或者開發(fā)人員想要將應(yīng)用程序和開發(fā)環(huán)境分開,等等。
先決條件
 |
啟動(dòng)配置類型
啟動(dòng)配置 保存一組用于啟動(dòng)程序的屬性。啟動(dòng)配置類型是一種可以在 Eclipse 平臺(tái)上啟動(dòng)的獨(dú)特程序。 |
|
如果您還沒安裝該程序,請(qǐng)下載 Eclipse V3.4(Ganymede)。在 Ganymede 中,套接字(socket)監(jiān)聽連接器被添加到 Remote Java Application 啟動(dòng)配置類型。Eclipse 最新的套接字監(jiān)聽連接器允許您打開 Java 調(diào)試器,它能夠監(jiān)聽特定套接字上的連接。可以從命令行選項(xiàng)打開被調(diào)試的程序,并將其連接到調(diào)試器。在 Ganymede 發(fā)布之前,僅有一個(gè)連接套接字的連接器,被調(diào)試的程序所在的機(jī)器必須是一個(gè)與調(diào)試器相連的調(diào)試主機(jī)。由于受到內(nèi)存和 CPU 不足的限制,要想讓移動(dòng)設(shè)備充當(dāng)主機(jī)是不現(xiàn)實(shí)的。
為了進(jìn)行遠(yuǎn)程調(diào)試,必須使用 Java Virtual Machine (JVM) V5.0 或更新版本,比如 IBM® J9 或 Sun Microsystem 的 Java SE Development Kit(JDK)。本文主要討論遠(yuǎn)程調(diào)試,而不是每個(gè) Eclipse 調(diào)試特性的細(xì)節(jié)。查看 參考資料 獲得更多關(guān)于使用 Eclipse 進(jìn)行調(diào)試的信息,并且可以找到上面提到的軟件。
JPDA 簡介
 |
常用縮寫詞
- JDI — Java 調(diào)試接口(Java Debug Interface)
- JDT — Java 開發(fā)工具(Java Development Tools)
- JDWP — Java 調(diào)試網(wǎng)絡(luò)協(xié)議(Java Debug Wire Protocol)
- JPDA — Java 平臺(tái)調(diào)試器架構(gòu)(Java Platform Debugger Architecture)
- JVM — Java 虛擬機(jī)(Java Virtual Machine)
- JVMDI — JVM 調(diào)試接口(JVM Debug Interface)
- JVMTI — JVM 工具接口(JVM Tool Interface)
- VM — 虛擬機(jī)(Virtual Machine)
|
|
Sun Microsystem 的 Java Platform Debugger Architecture (JPDA) 技術(shù)是一個(gè)多層架構(gòu),使您能夠在各種環(huán)境中輕松調(diào)試 Java 應(yīng)用程序。JPDA 由兩個(gè)接口(分別是 JVM Tool Interface 和 JDI)、一個(gè)協(xié)議(Java Debug Wire Protocol)和兩個(gè)用于合并它們的軟件組件(后端和前端)組成。它的設(shè)計(jì)目的是讓調(diào)試人員在任何環(huán)境中都可以進(jìn)行調(diào)試。JPDA 不僅能夠用于桌面系統(tǒng),而且能夠在嵌入式系統(tǒng)上很好地工作。
JVM Tool Interface (JVMTI) 規(guī)定必須為調(diào)試提供 VM(編輯注:從 Java V5 開始,將用 JVMTI 代替 Java V1.4 中的 JVMDI)。Java Debug Wire Protocol (JDWP) 描述調(diào)試信息的格式,以及在被調(diào)試的進(jìn)程和調(diào)試器前端之間傳輸?shù)恼?qǐng)求,調(diào)試器前端實(shí)現(xiàn) JDI,比如 Eclipse、Borland JBuilder 等。根據(jù) Sun 的 JPDA 規(guī)范,被調(diào)試的程序常常稱為 debuggee。JDI 是一個(gè)高級(jí)的接口,它定義用于遠(yuǎn)程調(diào)試的信息和請(qǐng)求。下面給出了調(diào)試器的架構(gòu)。
清單 1. Java 平臺(tái)調(diào)試器架構(gòu)
Components Debugger Interfaces
/ |--------------|
/ | VM |
debuggee -----( |--------------| <---- JVMTI - Java VM Tool Interface
\ | back-end |
\ |--------------|
/ |
comm channel --( | <------------ JDWP - Java Debug Wire Protocol
\ |
/ |--------------|
/ | front-end |
debugger -----( |--------------| <---- JDI - Java Debug Interface
\ | UI |
\ |--------------|
|
因此,任何第三方工具和基于 JPDA 的 VM 應(yīng)該都能協(xié)調(diào)工作。通過這個(gè)客戶機(jī)-服務(wù)器架構(gòu),您可以從運(yùn)行該平臺(tái)的本地工作站調(diào)試 Java 程序,甚至還可以通過網(wǎng)絡(luò)進(jìn)行遠(yuǎn)程調(diào)試。
在討論調(diào)試場景之前,我們先了解 JPDA 規(guī)范中的兩個(gè)術(shù)語:連接器和傳輸。連接器是一個(gè) JDI 抽象,用來在調(diào)試器應(yīng)用程序和目標(biāo) VM 之間建立連接。傳輸定義應(yīng)用程序如何進(jìn)行訪問,以及數(shù)據(jù)如何在前端和后端之間傳輸。連接器 “映射” 到可用的傳輸類型和連接模式。在 Sun 的 JPDA 參考實(shí)現(xiàn)中,為 Microsoft® Windows® 提供了兩個(gè)傳輸機(jī)制:套接字傳輸和共享內(nèi)存?zhèn)鬏敗?捎玫倪B接器:
- 連接套接字連接器
- 連接共享內(nèi)存連接器
- 監(jiān)聽套接字連接器
- 監(jiān)聽共享內(nèi)存連接器
- 啟動(dòng)命令行連接器
在調(diào)試器應(yīng)用程序和目標(biāo) VM 之間建立連接時(shí),有一端將用作服務(wù)器并監(jiān)聽連接。隨后,另一端將連接到監(jiān)聽器并建立一個(gè)連接。通過連接,調(diào)試器應(yīng)用程序或目標(biāo) VM 都可以充當(dāng)服務(wù)器。進(jìn)程之間的通信可以在同一個(gè)機(jī)器或不同的機(jī)器上運(yùn)行。
要遠(yuǎn)程調(diào)試 Java 程序,難點(diǎn)不是在調(diào)試器的前端,而是遠(yuǎn)程 Java 后端。不幸的是,Eclipse 幫助系統(tǒng)中為這方面提供的信息并不多。事實(shí)上,JDI 和 JVMTI 是分別由 Eclipse 和 Java 運(yùn)行時(shí)環(huán)境實(shí)現(xiàn)的。我們僅需要考慮 JDMP,因?yàn)樗c JVMTI 和 JDI 進(jìn)行通信所需的信息。JDWP 包含許多參數(shù),用于為遠(yuǎn)程 Java 應(yīng)用程序調(diào)用所需的程序。以下是本文用到的一些參數(shù)。
- -Xdebug
- 啟用調(diào)試特性。
- -Xrunjdwp:<sub-options>
- 在目標(biāo) VM 中加載 JDWP 實(shí)現(xiàn)。它通過傳輸和 JDWP 協(xié)議與獨(dú)立的調(diào)試器應(yīng)用程序通信。下面介紹一些特定的子選項(xiàng)。
從 Java V5 開始,您可以使用 -agentlib:jdwp 選項(xiàng),而不是 -Xdebug 和 -Xrunjdwp。但如果連接到 V5 以前的 VM,只能選擇 -Xdebug 和 -Xrunjdwp。下面簡單描述 -Xrunjdwp 子選項(xiàng)。
- transport
- 這里通常使用套接字傳輸。但是在 Windows 平臺(tái)上也可以使用共享內(nèi)存?zhèn)鬏敗?/dd>
- server
- 如果值為 y,目標(biāo)應(yīng)用程序監(jiān)聽將要連接的調(diào)試器應(yīng)用程序。否則,它將連接到特定地址上的調(diào)試器應(yīng)用程序。
- address
- 這是連接的傳輸?shù)刂贰H绻?wù)器為 n,將嘗試連接到該地址上的調(diào)試器應(yīng)用程序。否則,將在這個(gè)端口監(jiān)聽連接。
- suspend
- 如果值為 y,目標(biāo) VM 將暫停,直到調(diào)試器應(yīng)用程序進(jìn)行連接。
要獲得每個(gè)調(diào)試設(shè)置的詳細(xì)解釋,請(qǐng)參考 JPDA 文檔(參見 參考資料)。
清單 2 是一個(gè)示例,顯示如何在調(diào)試模式下啟動(dòng) VM 并監(jiān)聽端口 8765 的套接字連接。
清單 2. 作為調(diào)試服務(wù)器的目標(biāo) VM
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8765
|
清單 3 顯示如何使用位于 8000 端口的主機(jī) 127.0.0.1 上的套接字連接運(yùn)行中的調(diào)試器應(yīng)用程序。
清單 3. 作為調(diào)試客戶機(jī)的目標(biāo) VM
-Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000
|
Eclipse 中的遠(yuǎn)程調(diào)試特性
Eclipse 是一個(gè)圖形化 Java 調(diào)試器前端。JDI 在 org.eclipse.jdt.debug 包中實(shí)現(xiàn)。本文不詳細(xì)討論 JDI 實(shí)現(xiàn)。參見 參考資料 獲得關(guān)于 Eclipse JDT 和 Java JDI 技術(shù)的信息。
我們首先應(yīng)該知道要使用哪個(gè) Eclipse 連接器。要了解 Eclipse 提供的遠(yuǎn)程連接類型,您可以轉(zhuǎn)到 Eclipse 菜單并選擇 Run > Debug Configurations...,在 Remote Java Application 中添加一個(gè)啟動(dòng)配置,然后從下拉列表中選擇連接器。在 Ganymede 中共有兩個(gè)連接器:
- Socket Attach
- Socket Listen
對(duì)于監(jiān)聽套接字的連接器,Eclipse VM 將是與遠(yuǎn)程 Java 應(yīng)用程序連接的主機(jī)。對(duì)于連接套接字的連接器,目標(biāo) VM 將作為主機(jī)。這兩種連接器對(duì)應(yīng)用程序調(diào)試沒有影響,用戶可以任意選擇。但根據(jù)經(jīng)驗(yàn),需要使用速度更快、更強(qiáng)大的計(jì)算機(jī)作為 VM 調(diào)試主機(jī),因?yàn)樾枰?jì)算的資源很多。
在調(diào)試 Java 應(yīng)用程序之前,需要確保已經(jīng)為遠(yuǎn)程應(yīng)用程序啟用所有調(diào)試選項(xiàng)。如果選項(xiàng)信息不可用,您將收到一個(gè)錯(cuò)誤信息,比如 “Debug information is not available” 或 “Unable to install breakpoint due to missing line number”。您可以通過更改 Eclipse 菜單上的 Window > Preferences > Java > Compiler 來修改設(shè)置。
圖 1. Eclipse 中的調(diào)試選項(xiàng)
遠(yuǎn)程調(diào)試應(yīng)用程序
現(xiàn)在,我們已經(jīng)準(zhǔn)備好遠(yuǎn)程調(diào)試應(yīng)用程序。我們分步執(zhí)行:
- 1. 使用簡單類創(chuàng)建一個(gè) Java 項(xiàng)目
- 我們?yōu)檎{(diào)試創(chuàng)建一個(gè)簡單類。清單 4 給出了示例代碼。
清單 4. 調(diào)試示例代碼
package com.ibm.developerWorks.debugtest;
public class test {
public static void main(String[] args) {
System.out.println("This is a test.");
}
}
|
- 2. 設(shè)置一個(gè)斷點(diǎn)
- 在代碼中設(shè)置一個(gè)斷點(diǎn)。在這個(gè)例子中,我們?cè)?System.out.println("This is a test."); 這行中設(shè)置斷點(diǎn)。
圖 2. 在 Eclipse 中設(shè)置斷點(diǎn)
- 3. 從本地調(diào)試應(yīng)用程序
- 在調(diào)試應(yīng)用程序之前,確保已經(jīng)為項(xiàng)目啟用圖 1 中描述的調(diào)試選項(xiàng)。從本地調(diào)試應(yīng)用程序是沒有必要的,但是這可以確保是否所有調(diào)試信息都可用。右鍵單擊 Java 項(xiàng)目,并選擇 Debug As,然后選擇 Java Application(參見圖 3)。如果應(yīng)用程序在斷點(diǎn)處停止執(zhí)行,則表明調(diào)試信息正確顯示。這時(shí),可以繼續(xù)使用這些調(diào)試特性,比如顯示調(diào)試堆棧、變量或斷點(diǎn)管理等等。
圖 3. 從本地調(diào)試應(yīng)用程序
- 4. 導(dǎo)出 Java 項(xiàng)目
- 我們將使用這個(gè)應(yīng)用程序作為調(diào)試目標(biāo)。右鍵單擊 Java 項(xiàng)目,選擇 Export,然后選擇 Java,最后選擇 JAR file 或 Runnable JAR file 導(dǎo)出項(xiàng)目。將在指定的位置生成 JAR 文件。注意,如果 Java 源代碼與目標(biāo)應(yīng)用程序不匹配,調(diào)試特性將不能正常工作。
- 5. 手動(dòng)運(yùn)行 Java 應(yīng)用程序
- 打開控制臺(tái)手動(dòng)啟動(dòng)應(yīng)用程序,確保正確配置了 Java 運(yùn)行時(shí)環(huán)境。
清單 5. 調(diào)用 Java 應(yīng)用程序的示例
- 6. 遠(yuǎn)程調(diào)試應(yīng)用程序
- 將 JAR 文件復(fù)制到遠(yuǎn)程計(jì)算機(jī)或同一臺(tái)計(jì)算機(jī)上的適當(dāng)位置,調(diào)用調(diào)試服務(wù)器,然后為它添加一個(gè)客戶機(jī)。簡單的 Java 應(yīng)用程序就可以充當(dāng)調(diào)試服務(wù)器或客戶機(jī)。您可以在 Eclipse 中選擇 Socket Attach 或 Socket Listen 連接類型,這取決于特定的配置。接下來的兩個(gè)小節(jié)將學(xué)習(xí)如何將應(yīng)用程序作為服務(wù)器或客戶機(jī)運(yùn)行。
作為調(diào)試服務(wù)器的目標(biāo) VM
下面這個(gè)示例遠(yuǎn)程調(diào)用 Java 應(yīng)用程序作為調(diào)試服務(wù)器,并在端口 8000 監(jiān)聽套接字連接。目標(biāo) VM 將暫停,直到調(diào)試器連接。
清單 6. Eclipse 連接套接字模式下的 VM 調(diào)用示例
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address="8000" -jar
test.jar
|
使用遠(yuǎn)程啟動(dòng)配置啟動(dòng) Eclipse,并指定遠(yuǎn)程應(yīng)用程序的目標(biāo) VM 地址。為此,單擊 Run > Debug Configurations,然后在 Eclipse 菜單中雙擊 Remote Java Application。從最新創(chuàng)建的啟動(dòng)配置中為目標(biāo)應(yīng)用程序指定 IP 和端口。為了在同一臺(tái)機(jī)器上運(yùn)行遠(yuǎn)程應(yīng)用程序,僅需將主機(jī) IP 指定為 localhost 或 127.0.0.1。
圖 4. 連接套接字連接的配置
選擇 Allow termination of remote VM 選項(xiàng)終止在應(yīng)用程序調(diào)試期間連接的 VM。
圖 5. Eclipse 中的 Terminate 按鈕
作為調(diào)試客戶機(jī)的目標(biāo) VM
第二個(gè)示例使用一個(gè)簡單的 Java 應(yīng)用程序作為調(diào)試客戶機(jī),并且調(diào)試器前端作為調(diào)試服務(wù)器。Eclipse 使用套接字監(jiān)聽模式連接類型進(jìn)行監(jiān)聽。必須先啟動(dòng)調(diào)試前端來監(jiān)聽特定的端口。圖 6 給出一個(gè)用于設(shè)置監(jiān)聽的示例配置。
圖 6. 監(jiān)聽套接字連接的配置
單擊 Eclipse Debug 按鈕,狀態(tài)欄將顯示消息 “waiting for vm to connect at port 8000...”。看到這個(gè)消息后,啟動(dòng)遠(yuǎn)程應(yīng)用程序。清單 7 顯示了如何將 Java 應(yīng)用程序作為調(diào)試客戶機(jī)并調(diào)用它,然后使用端口 8000 上的主機(jī) 127.0.0.1 的套接字將其連接到一個(gè)正在運(yùn)行的調(diào)試器應(yīng)用程序。
清單 7. Eclipse 監(jiān)聽套接字連接模式中的 VM 調(diào)用示例
java -Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000,suspend=y
-jar test.jar
|
如果一切進(jìn)行順利,將會(huì)顯示一個(gè)調(diào)試透視圖幫助調(diào)試應(yīng)用程序,并且遠(yuǎn)程 Java 應(yīng)用程序?qū)⒄MV埂_@類似于步驟 3 中的本地調(diào)試(參見圖 3)。在這里,您可以使用標(biāo)準(zhǔn)的調(diào)試特性,比如設(shè)置斷點(diǎn)和值、單步執(zhí)行等。
注意:一定是自己編譯的src才可。即:src要與調(diào)試的程序一致。
結(jié)束語
本文演示如何使用 Eclipse 內(nèi)置的遠(yuǎn)程 Java 應(yīng)用程序配置類型對(duì)應(yīng)用程序執(zhí)行遠(yuǎn)程調(diào)試。介紹了如何設(shè)置 Java 應(yīng)用程序以調(diào)用遠(yuǎn)程調(diào)試,并幫助您理解 Eclipse 提供的連接器。最后,您還學(xué)習(xí)了如何將這些技術(shù)應(yīng)用到項(xiàng)目中。