久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Eclipse遠(yuǎn)程調(diào)試Tomcat

 muyable 2014-10-03

最近,,一直在研究Tomcat的工作內(nèi)幕,主要的方法就是參考《How Tomcat Works》 這本書(shū)和Tomcat 5.5.26的源代碼,。

 

Tomcat的代碼結(jié)構(gòu)還是比較清晰的,,注釋也比較全,。但是代碼畢竟是靜態(tài)的,難以徹底弄清類與類之間的協(xié)作關(guān)系,,以及運(yùn)行時(shí)對(duì)象的交互關(guān)系,。

 

如果能對(duì)Tomcat的啟動(dòng)、處理請(qǐng)求和停止的過(guò)程進(jìn)行斷點(diǎn)調(diào)試,,看清Tomcat的每一步行蹤,,那么就能解決上面的問(wèn)題了。

 

于是,,又一個(gè)問(wèn)題出來(lái)了:如何使用Eclipse遠(yuǎn)程調(diào)試Tomcat ,?

 

上網(wǎng)查了一些資料,相關(guān)的文章還是很多的,。我簡(jiǎn)單梳理了一下解決方案及原理,,順便熟悉了Tomcat的啟動(dòng)腳本。

 

如何遠(yuǎn)程調(diào)試JVM,?

遠(yuǎn)程調(diào)試Tomcat,,本質(zhì)上就是遠(yuǎn)程調(diào)試JVM。倒不是需要了解JVM自身的運(yùn)行細(xì)節(jié),,而是要了解JVM上應(yīng)用程序的運(yùn)行細(xì)節(jié),。

無(wú)論如何,我們都要獲取JVM運(yùn)行時(shí)的內(nèi)部信息(比如查看調(diào)試信息),,并對(duì)JVM的運(yùn)行流程進(jìn)行控制(比如單步執(zhí)行),,才能達(dá)到調(diào)試的目的。

 

這個(gè)事情光靠調(diào)試器本身,,肯定是做不到的,。不然,JVM的安全性就大打折扣了,。除非JVM提供某種“后門”,,供調(diào)試器查詢一些運(yùn)行時(shí)信息,并允許調(diào)試器發(fā)送一些控制命令,。

 

不得不感慨,,JVM的強(qiáng)大。從J2SE 1.4.2開(kāi)始,,就已經(jīng)提出并實(shí)現(xiàn)了JavaTM Platform Debugger Architecture ,,簡(jiǎn)稱JPDA。

 

JPDA簡(jiǎn)介

顧名思義,,JPDA為Java平臺(tái)上的調(diào)試器定義了一個(gè)標(biāo)準(zhǔn)的體系結(jié)構(gòu),。該體系結(jié)構(gòu)包括3個(gè)主要組成部分:JVM TI、JDI和JDWP,。

 

JVM TI的全稱是Java Virtual Machine Tool Interface,,它定義了JVM為了支持調(diào)試而必須提供的功能及相應(yīng)的訪問(wèn)接口,。這些訪問(wèn)接口是以本地語(yǔ)言的形式提供的,由JVM(比如Sun公司的HotSpot VM)負(fù)責(zé)實(shí)現(xiàn),。

不過(guò),,JVM TI只是JVM提供的一系列函數(shù),調(diào)試器(特別是遠(yuǎn)程的調(diào)試器)如何調(diào)用呢,?其實(shí)啊,,JVM TI的直接客戶端并不是調(diào)試器,而是一個(gè)稱為“JPDA back-end”的東東,。這個(gè)東東應(yīng)該是屬于JVM的一部分,,在SUN JRE的bin目錄下可以找到j(luò)dwp.dll(jdwp.so)的庫(kù)文件,這就是JPDA back-end的實(shí)現(xiàn),。按我理解,,JPDA back-end提供了各種訪問(wèn)方式(共享內(nèi)存,Socket),,通過(guò)這些方式接收調(diào)試器的請(qǐng)求,然后調(diào)用JVM TI接口,。

 

JDI的全稱是Java Debug Interface,,它定義了訪問(wèn)JVM TI接口的高層API,以純Java語(yǔ)言提供,,由JDK實(shí)現(xiàn)(在Sun JDK的tools.jar可以找到),。調(diào)試器直接使用JDI來(lái)實(shí)現(xiàn)調(diào)試的功能。與JPDA back-end相對(duì)應(yīng),,JDI實(shí)現(xiàn)的角色就是JPDA front-end,。

 

JDWP的全稱是Java Debug Wire Protocol,它定義了JPDA front-end和JPDA back-end之間通訊信息的二進(jìn)制格式,。這里的通訊信息主要包括兩種:調(diào)試器發(fā)送給JVM的請(qǐng)求信息和JVM發(fā)送給調(diào)試器的調(diào)試信息,。

 

總結(jié)一下,調(diào)試器 調(diào)用JDK提供的JDI實(shí)現(xiàn) (JPDA front-end),,經(jīng)由JDWP協(xié)議 ,,和JVM自帶的JPDA back-end (jdwp.dll, jdwp.so, ...)進(jìn)行通訊。JPDA back-end 通過(guò)調(diào)用JVM TI接口 ,,從而獲知調(diào)試信息,,或發(fā)送控制命令。然后,,JPDA back-end 將調(diào)試信息或命令執(zhí)行結(jié)果,,通過(guò)JDWP協(xié)議 ,返回給調(diào)試器 ,。

 

如何啟用JPDA

默認(rèn)情況下,,JVM并沒(méi)有啟用JPDA back-end,。需要在啟動(dòng)JVM的命令行加載以下參數(shù):

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

 

-Xdebug

啟用調(diào)試特性

-Xrunjdwp

啟用JDWP實(shí)現(xiàn),它包含若干子選項(xiàng):

transport=dt_socket

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

address=8000

JVM在8000端口上監(jiān)聽(tīng)請(qǐng)求。

server=y

y表示啟動(dòng)的JVM是被調(diào)試者,。如果為n,,則表示啟動(dòng)的JVM是調(diào)試器。

suspend=y

y表示啟動(dòng)的JVM會(huì)暫停等待,,直到調(diào)試器連接上,。

 

suspend=y這個(gè)選項(xiàng)很重要。如果你想從Tomcat啟動(dòng)的一開(kāi)始就進(jìn)行調(diào)試,,那么就必須設(shè)置suspend=y,。

 

Tomcat的啟動(dòng)腳本

只要Tomcat啟動(dòng)時(shí),啟用了JPDA,,那么就可以被調(diào)試,。而Tomcat默認(rèn)是不啟用JPDA的,需要我們手動(dòng)開(kāi)啟,。

 

開(kāi)啟JPDA的方法也很簡(jiǎn)單,,對(duì)Tomcat的啟動(dòng)腳本做點(diǎn)修改,把啟動(dòng)JPDA的命令行參數(shù)添加進(jìn)去,,就可以了,。

 

不過(guò)Tomcat啟動(dòng)腳本還是有點(diǎn)復(fù)雜的,并不是簡(jiǎn)單的”java ...“,。我們先簡(jiǎn)單的梳理一下,。

 

在Tomcat 5.5.26發(fā)行版的bin目錄下,有N多腳本,,其中與Tomcat啟停有關(guān)的腳本是(以Windows為例):

startup.bat        //啟動(dòng)Tomcat

shutdown.bat   //停止Tomcat

catalina.bat       //包含啟動(dòng)/停止Tomcat的核心邏輯

 

startup.bat和shutdown.bat都是通過(guò)調(diào)用catalina.bat來(lái)實(shí)現(xiàn)啟動(dòng)和停止的功能,,因此他倆的代碼都很少。主要的邏輯都在catalina.bat中,。

 

catalina.bat是個(gè)強(qiáng)大的腳本,,通過(guò)參數(shù),可以執(zhí)行各種動(dòng)作,,包括debug run start stop version等,。

如果我們直接執(zhí)行catalina.bat,就可以看到它的用法說(shuō)明:

 

直接執(zhí)行catalina.bat時(shí)的輸出

 

startup.bat,,其實(shí)就是執(zhí)行catalina.bat start,;shutdown.bat,其實(shí)就是執(zhí)行catalina.bat stop。

不難猜到,,我們可以寫一個(gè)jdpa.bat,,直接調(diào)用catalina.bat jpda start,應(yīng)該就可以啟用JPDA,。我們拷貝一份startup.bat,,把下面這行

call "%EXECUTABLE%" start %CMD_LINE_ARGS%

修改成

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

 

不過(guò),-Xdebug -Xrunjdwp:transport=dt_socket, address=8000,server=y,suspend=y,,這些選項(xiàng)參數(shù)怎么傳遞給catalina.bat呢,?

看看catalina.bat前面的注釋,server的值默認(rèn)就是y,,transport的值是變量JPDA_TRANSPORT,,address的值是變量JPDA_ADDRESS,suspend的值是變量JPDA_SUSPEND ,。如果沒(méi)有顯式地復(fù)制,,這些變量的值默認(rèn)是dt_shmem jdbconn n(默認(rèn)值表示使用共享內(nèi)存作為傳輸方式)。這些默認(rèn)值不是我們需要的,,Eclisep的遠(yuǎn)程調(diào)試目前只支持套接字傳輸,。在調(diào)用catalina.bat jpda start之前,我們給這些變量設(shè)置恰當(dāng)?shù)闹担?/p>

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

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

 

然后,,直接執(zhí)行jpda.bat,,Tomcat就運(yùn)行在JPDA可調(diào)式模式下:

啟用JPDA的Tomcat

 

從上圖可以看出,Tomcat的JPDA使用套接字傳輸,,監(jiān)聽(tīng)在8000端口。Tomcat的啟動(dòng)已經(jīng)暫停,,只有調(diào)試器連接上來(lái),,才會(huì)繼續(xù)啟動(dòng)。

 

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

 


 

@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

 


 

 

在Eclipse中遠(yuǎn)程調(diào)試Tomcat

首先將Tomcat 5.5.26的源代碼分為container connectors jasper servletapi build五個(gè)項(xiàng)目,導(dǎo)入到Eclipse中,。啟動(dòng)相關(guān)的代碼主要在container中,,就以它為當(dāng)前項(xiàng)目,打開(kāi)”Debug Configurations“對(duì)話框,。

然后創(chuàng)建一個(gè)”Remote Java Application“,,Connection Type選擇”Standard (Socket Attach)“,Host填寫localhost(Tomcat所在的主機(jī)地址),,Port填寫8000,。最后點(diǎn)擊”Apply“保存。

Eclipse的Debug Configurations對(duì)話框中配置遠(yuǎn)程調(diào)試

 

首先確保已經(jīng)執(zhí)行了jpda.bat,Tomcat正在等待調(diào)試器連接,;然后執(zhí)行上述的Debug Configuration,,Eclipse就可以連上Tomcat。

 

Tomcat的啟動(dòng)是從Bootstrap的main方法開(kāi)始,,我在第一行代碼處設(shè)置了斷點(diǎn),,Tomcat的啟動(dòng)就停在了這一行:

 

斷點(diǎn)調(diào)試Tomcat的啟動(dòng)過(guò)程

 

接著,讓Tomcat繼續(xù)執(zhí)行,,我們可以看到,,控制臺(tái)輸出了啟動(dòng)信息。

Tomcat在JPDA模式下繼續(xù)啟動(dòng)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多