Tomcat熱部署的實現原理

2022-09-11 04:33:12 字數 3874 閱讀 7222

tomcat熱部署機制

對於j**a應用程式來說,熱部署就是在執行時更新j**a類檔案。在基於j**a的應用伺服器實現熱部署的過程中,類裝入器扮演著重要的角色。大多數基於j**a的應用伺服器,包括ejb伺服器和servlet容器,都支援熱部署。類裝入器不能重新裝入乙個已經裝入的類,但只要使用乙個新的類裝入器例項,就可以將類再次裝入乙個正在執行的應用程式。

我們知道,現在大多數的web伺服器都支援熱部署,而對於熱部署的實現機制,網上講的卻不夠完善,下面我們就tomcat的熱部署實現機制,講解一下它是如何實現的:

tomcat的容器實現熱部署使用了兩種機制:

classloader重寫,通過自定義classloader載入相應的jsp編譯後的class到jvm中。 通過動態修改記憶體中的位元組碼,將修改過的class再次裝載到jvm中。

tomcat通過org.apache.jasper.servlet.jasperloader實現了對jsp的載入,下面做個測試: 1. 新建乙個web工程,並編寫乙個jsp頁面,在jsp頁面中輸出該頁面的classloader,<%system.out.print(this.getclass().getclassloader());%>.

2. 啟動web伺服器,開啟jsp頁面,我們可以看到後台輸出,該jsp的classloader是jasperloader的乙個例項。

3. 修改jsp,儲存並重新整理jsp頁面,再次檢視後台輸出,此classloader例項已經不是剛才那個了,也就是說tomcat通過乙個新的classloader再次裝載了該jsp。

4. 其實,對於每個jsp頁面tomcat都使用了乙個獨立的classloader來裝載,每次修改完jsp後,tomcat都將使用乙個新的classloader來裝載它。

通過**修改記憶體中class的位元組碼

下面我們看一下如何通過**修改記憶體中的class位元組碼:

以下是乙個簡單的熱部署**實現類(**比較粗糙,也沒什麼判斷):

package

agent;

import

j**a.lang.instrument.classfiletransformer;

import

j**a.lang.instrument.instrumentation;

import

j**a.util.set;

import

j**a.util.timer;

import

j**a.util.treeset;

public

class

hotagent

}package

agent;

import

j**a.lang.instrument.classfiletransformer;

importj**a.lang.instrument.illegalclassformatexception;

import

j**a.lang.instrument.instrumentation;

import

j**a.security.protectiondomain;

public

class classtransform. implements

classfiletransformer

/*** 此方法在redefineclasses時或者初次載入時會呼叫,也就是說在class被再次載入時會被呼叫,

* 並且我們通過此方法可以動態修改class位元組碼,實現類似**之類的功能,具體方法可使用asm或者j**asist,

* 如果對位元組碼很熟悉的話可以直接修改位元組碼。

*/public

byte

transform(classloader loader, string classname,

class

<?>classbeingredefined, protectiondomain protectiondomain,

byte classfilebuffer)throws

illegalclassformatexception

}package

agent;

import

j**a.io.inputstream;

import

j**a.lang.instrument.classdefinition;

import

j**a.lang.instrument.instrumentation;

import

j**a.util.timertask;

public

class reloadtask extends

timertask

@override

public

void

run()

}catch

(exception ex)

}private

byte loadclassbytes(class cls,string clsname) throws

exception

}

以上是基本實現**,需要元件為: 1.hotagent(預載入) 2.classtransform(在載入class的時候可以修改class的位元組碼),本例中沒用到 3.reloadtask(class定時載入器,以上**僅供參考) 4.meta-inf/manifest.mf內容為:(引數一:支援class重定義;引數二:預載入類)

can-redefine-classes: true premain-class: agent.hotagent

5.將以上元件打包成jar檔案(到此,元件已經完成,下面為編寫測試類檔案)。 6.新建乙個j**a工程,編寫乙個j**a邏輯類,並編寫乙個test類,在該測試類中呼叫邏輯類的方法,下面看下測試類**:

package

test.redefine;

public

class

bean1

}package

test.redefine;

public

class

test

}}

執行測試類:

j**a –j**aagent:agent.jar test.redefine.test

在測試類中,我們使用了乙個死迴圈,定時呼叫邏輯類的方法。我們可以修改bean1中的方法實現,將在不同時間看到不同的輸出結果,關於技術細節也沒什麼好講的了,相信大家都能明白。

tomcat 熱部署配置

<

host

autodeploy

="true"

name

="localhost"

unpackwars

="true"

xmlnamespaceaware

="false"

xmlvalidation

="false"

>

<

context

docbase

="cpcweb"

path

="/cpcweb"

reloadable

="true"

source

="org.wp_keywordlink"

><

a href

=""title

="eclipse importnew主頁"

target

="_blank"

>eclipse

a>

span

>

.jst.j2ee.server:cpcweb"/>

host

>

autodeploy=」true」 — 自動部署 reloadable=」true」 — 自動載入

Tomcat中jsp熱部署實現原理

大體的類通訊時序圖是這樣的 其中上文說的時間戳的校驗邏輯主要封裝在jdtcompiler的isoutdated方法裡面,這個方法的主要源 如下 在實驗的時候我比較好奇就收到把這個值改為了40,果然jsp並沒有及時生效,而是過了40秒之後才生效。第二個紅框檢測的是獲取work目錄下的class檔案的物...

Tomcat中jsp熱部署實現原理

大體的類通訊時序圖是這樣的 其中上文說的時間戳的校驗邏輯主要封裝在jdtcompiler的isoutdated方法裡面,這個方法的主要源 如下 在實驗的時候我比較好奇就收到把這個值改為了40,果然jsp並沒有及時生效,而是過了40秒之後才生效。第二個紅框檢測的是獲取work目錄下的class檔案的物...

Tomcat的熱部署

tomcat的熱部署 以後就不用重起了 tomcat上的部署問題,有時候也是個麻煩的問題,要是不採用熱部署,我們就只能每次對原來的檔案做一次改動的時候就要重新部署,而每次重新部署都要關閉tomcat,部署完重起tomcat,可見這是乙個多麼煩人的事情。現在,我們可以採用熱部署了,以後,就不用做凡人的...