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位元組碼:
以下是乙個簡單的熱部署**實現類(**比較粗糙,也沒什麼判斷):
packageagent;
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類,在該測試類中呼叫邏輯類的方法,下面看下測試類**:
packagetest.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,可見這是乙個多麼煩人的事情。現在,我們可以採用熱部署了,以後,就不用做凡人的...