eclipse遠程調試(windows)

JPDA簡介java

顧名思義,JPDA爲Java平臺上的調試器定義了一個標準的體系結構。該體系結構包括3個主要組成部分:JVM TI、JDI和JDWP。linux

 

JVM TI的全稱是Java Virtual Machine Tool Interface,它定義了JVM爲了支持調試而必須提供的功能及相應的訪問接口。這些訪問接口是以本地語言的形式提供的,由JVM(好比Sun公司的HotSpot VM)負責實現。centos

不過,JVM TI只是JVM提供的一系列函數,調試器(特別是遠程的調試器)如何調用呢?其實啊,JVM TI的直接客戶端並非調試器,而是一個稱爲「JPDA back-end」的東東。這個東東應該是屬於JVM的一部分,在SUN JRE的bin目錄下能夠找到jdwp.dll(jdwp.so)的庫文件,這就是JPDA back-end的實現。按我理解,JPDA back-end提供了各類訪問方式(共享內存,Socket),經過這些方式接收調試器的請求,而後調用JVM TI接口。api

 

JDI的全稱是Java Debug Interface,它定義了訪問JVM TI接口的高層API,以純Java語言提供,由JDK實現(在Sun JDK的tools.jar能夠找到)。調試器直接使用JDI來實現調試的功能。與JPDA back-end相對應,JDI實現的角色就是JPDA front-end。tomcat

 

JDWP的全稱是Java Debug Wire Protocol,它定義了JPDA front-end和JPDA back-end之間通信信息的二進制格式。這裏的通信信息主要包括兩種:調試器發送給JVM的請求信息和JVM發送給調試器的調試信息。socket

 

總結一下,調試器 調用JDK提供的JDI實現 (JPDA front-end),經由JDWP協議 ,和JVM自帶的JPDA back-end (jdwp.dll, jdwp.so, ...)進行通信。JPDA back-end 經過調用JVM TI接口 ,從而獲知調試信息,或發送控制命令。而後,JPDA back-end 將調試信息或命令執行結果,經過JDWP協議 ,返回給調試器 。tcp

 

如何啓用JPDA函數

默認狀況下,JVM並無啓用JPDA back-end。須要在啓動JVM的命令行加載如下參數:ui

-Xdebug -Xrunjdwp:transport=dt_socket, address=8000,server=y,suspend=ythis

 

-Xdebug

啓用調試特性

-Xrunjdwp

啓用JDWP實現,它包含若干子選項:

transport=dt_socket

JPDA front-end和back-end之間的傳輸方法。dt_socket表示使用套接字傳輸。

address=8000

JVM在8000端口上監聽請求。

server=y

y表示啓動的JVM是被調試者。若是爲n,則表示啓動的JVM是調試器。

suspend=y

y表示啓動的JVM會暫停等待,直到調試器鏈接上。

 

suspend=y這個選項很重要。若是你想從Tomcat啓動的一開始就進行調試,那麼就必須設置suspend=y。

 

Tomcat的啓動腳本

只要Tomcat啓動時,啓用了JPDA,那麼就能夠被調試。而Tomcat默認是不啓用JPDA的,須要咱們手動開啓。

 

開啓JPDA的方法也很簡單,對Tomcat的啓動腳本作點修改,把啓動JPDA的命令行參數添加進去,就能夠了。

 

不過Tomcat啓動腳本仍是有點複雜的,並非簡單的」java ...「。咱們先簡單的梳理一下。

 

在Tomcat 5.5.26發行版的bin目錄下,有N多腳本,其中與Tomcat啓停有關的腳本是(以Windows爲例):

startup.bat        //啓動Tomcat

shutdown.bat   //中止Tomcat

catalina.bat       //包含啓動/中止Tomcat的核心邏輯

 

startup.bat和shutdown.bat都是經過調用catalina.bat來實現啓動和中止的功能,所以他倆的代碼都不多。主要的邏輯都在catalina.bat中。

 

catalina.bat是個強大的腳本,經過參數,能夠執行各類動做,包括debug run start stop version等。

若是咱們直接執行catalina.bat,就能夠看到它的用法說明:

 

直接執行catalina.bat時的輸出

 

startup.bat,其實就是執行catalina.bat start;shutdown.bat,其實就是執行catalina.bat stop。

不難猜到,咱們能夠寫一個jdpa.bat,直接調用catalina.bat jpda start,應該就能夠啓用JPDA。咱們拷貝一份startup.bat,把下面這行

call "%EXECUTABLE%" start %CMD_LINE_ARGS%

修改爲

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

 

不過,-Xdebug -Xrunjdwp:transport=dt_socket, address=8000,server=y,suspend=y,這些選項參數怎麼傳遞給catalina.bat呢?

看看catalina.bat前面的註釋,server的值默認就是y,transport的值是變量JPDA_TRANSPORT,address的值是變量JPDA_ADDRESS,suspend的值是變量JPDA_SUSPEND 。若是沒有顯式地複製,這些變量的值默認是dt_shmem jdbconn n(默認值表示使用共享內存做爲傳輸方式)。這些默認值不是咱們須要的,Eclisep的遠程調試目前只支持套接字傳輸。在調用catalina.bat jpda start以前,咱們給這些變量設置恰當的值:

set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=8000
set JPDA_SUSPEND=y

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

 

而後,直接執行jpda.bat,Tomcat就運行在JPDA可調式模式下:

啓用JPDA的Tomcat

 

從上圖能夠看出,Tomcat的JPDA使用套接字傳輸,監聽在8000端口。Tomcat的啓動已經暫停,只有調試器鏈接上來,纔會繼續啓動。

 

我把jpda.bat的完整內容列在下面,其中黑體部分,在startup.bat基礎上添加的代碼:

 

 

@echo off
if "%OS%" == "Windows_NT" setlocal
rem ---------------------------------------------------------------------------
rem Jpda script for the CATALINA Server
rem
rem $Id: jpda.bat 302918 2004-05-27 18:25:11Z yoavs $
rem ---------------------------------------------------------------------------

rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd%
if not "%CATALINA_HOME%" == "" goto gotHome
set CATALINA_HOME=%CURRENT_DIR%
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
cd ..
set CATALINA_HOME=%cd%
cd %CURRENT_DIR%
:gotHome
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat

rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find %EXECUTABLE%
echo This file is needed to run this program
goto end
:okExec

rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs

set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=8000
set JPDA_SUSPEND=y
 

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

:end

 

若是是linux系統,整理以centos7爲例:

經過tar包安裝的tomcat找到catalina.sh文件在文件的第一行添加

declare -x CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8099"

經過yum按的tomcat找到tomcat的server配置文件,在文件的第一行添加

declare -x CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8099"

 

經過以下兩個命令查看端口監聽狀況是否存在8099端口在監聽。

# netstat -lntp #查看監聽(Listen)的端口
# netstat -antp #查看全部創建的TCP鏈接

 

也有可能你的centos7系統防火牆規則的設定你還須要開放8099端口:


firewall-cmd --zone=public --add-port=8099/tcp --permanent
出現success代表添加成功

命令含義:

--zone #做用域
--add-port=8099/tcp  #添加端口,格式爲:端口/通信協議
--permanent   #永久生效,沒有此參數重啓後失效
而後重啓防火牆

 

在Eclipse中遠程調試Tomcat

首先將Tomcat 5.5.26的源代碼分爲container connectors jasper servletapi build五個項目,導入到Eclipse中。啓動相關的代碼主要在container中,就以它爲當前項目,打開」Debug Configurations「對話框。

而後建立一個」Remote Java Application「,Connection Type選擇」Standard (Socket Attach)「,Host填寫localhost(Tomcat所在的主機地址),Port填寫8000。最後點擊」Apply「保存。

Eclipse的Debug Configurations對話框中配置遠程調試

 

首先確保已經執行了jpda.bat,Tomcat正在等待調試器鏈接;而後執行上述的Debug Configuration,Eclipse就能夠連上Tomcat。

 

Tomcat的啓動是從Bootstrap的main方法開始,我在第一行代碼處設置了斷點,Tomcat的啓動就停在了這一行:

 

斷點調試Tomcat的啓動過程

 

接着,讓Tomcat繼續執行,咱們能夠看到,控制檯輸出了啓動信息。

Tomcat在JPDA模式下繼續啓動

相關文章
相關標籤/搜索