摘要:而熱部署技術(shù)能夠幫助開發(fā)人員減少重新部署的等待時(shí)間。本文的目的為調(diào)研熱部署的技術(shù)現(xiàn)狀及其對(duì)開發(fā)效率的幫助,并簡(jiǎn)單梳理其技術(shù)實(shí)現(xiàn)的難點(diǎn)。熱部署技術(shù)總結(jié)熱部署目前有多種技術(shù)實(shí)現(xiàn)官方開源商業(yè)。
開發(fā)、自測(cè)、聯(lián)調(diào)期間代碼可能會(huì)被頻繁地修改,通常即使只增加了一行代碼,都需要重啟容器以檢查執(zhí)行效果。而熱部署技術(shù)能夠幫助開發(fā)人員減少重新部署的等待時(shí)間。本文的目的為調(diào)研熱部署的技術(shù)現(xiàn)狀及其對(duì)開發(fā)效率的幫助,并簡(jiǎn)單梳理其技術(shù)實(shí)現(xiàn)的難點(diǎn)。
熱部署技術(shù) 總結(jié)JVM熱部署目前有多種技術(shù)實(shí)現(xiàn):官方、開源、商業(yè)。其中商業(yè)的JRebel功能強(qiáng)大,涵蓋了日常開發(fā)中大部分熱更新場(chǎng)景。以團(tuán)隊(duì)中一個(gè)基于Tomcat + Spring的業(yè)務(wù)后臺(tái)為例,修改代碼后,本地冷啟動(dòng)耗時(shí)4.5min,本地?zé)岵渴鸬臅r(shí)間則小于1s,極大改善了開發(fā)效率。
官方實(shí)現(xiàn)當(dāng)前JVM和JVMTI(JVM Tool Interface)規(guī)范中通過相應(yīng)的agent機(jī)制支持的retransformClass/redefineClass操作可以在加載前和加載后動(dòng)態(tài)修改類的內(nèi)容,從Java 5開始,這一功能還通過Instrumentation API直接提供給Java應(yīng)用使用,但是其適用范圍是受限的:只能修改已有方法的方法體。
以下摘自 JVM(TM) Tool Interface 1.2.3
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, change modifiers, or change inheritance. These restrictions may be lifted in future versions. See the error return description below for information on error codes returned if an unsupported redefinition is attempted.
IDE的edit-and-continue功能(Intellij Idea為Update Application)就用到了這種被稱為HotSwap的熱部署技術(shù),但是它的限制太大,完全無法滿足實(shí)際開發(fā)中的需求。
Dynamic Code Evolution VM(DCEVM)這是一個(gè)由JKU主導(dǎo)的、基于HotSpot VM的研究項(xiàng)目,誕生于2010年。該項(xiàng)目希望能動(dòng)態(tài)修改類的任意元素,包括成員、方法、注解、繼承等而無需重啟JVM。目前的light版已經(jīng)支持到Java 8 update 144, build 2。
HotSwapAgent基于DCEVM構(gòu)建的開源項(xiàng)目,其完成度要高于DCEVM,目前已發(fā)布1.0版。對(duì)于常見的IDE、IoC/ORM/Log框架、J2EE應(yīng)用容器的支持比較完善。根據(jù)官方文檔,HA支持下列特性。
Add/remove/modify class fields.
Add/remove/modify methods. Add/remove/modify method annotations
Add/remove/modify classes including anonymous classes. HotswapAgent handless correct anonymous class redefinitions.
Add/remove static member of classes. HotswapAgent handles static member initialization.
Add/remove enum values
Refresh framework and application server settings
JRebelJava世界中大名鼎鼎的熱部署解決方案,熱部署特性與上面提到的HotSwapAgent類似。當(dāng)然作為一款商業(yè)軟件,它支持的框架、IDE、J2EE應(yīng)用容器的種類都更多,總計(jì)100+;同時(shí)支持Hotspot VM和Oracle VM;文檔和社區(qū)支持非常完善,很容易上手。
最重要的是,沒錢的碼農(nóng)可以通過贊助官方的Social Plan免費(fèi)激活JRebel!
JRebel實(shí)測(cè)測(cè)試環(huán)境為團(tuán)隊(duì)使用的Tomcat + Spring + SpringMvc。
以下是實(shí)際開發(fā)中常見的改動(dòng)類型的測(cè)試結(jié)果?!綪ass】為支持,【Fail】為不支持。
【Pass】在Spring和SpringMvc的配置Xml中增加Bean定義
【Pass】新增Controller類,新增、修改Controller注解
【Pass】新增、修改RequestHandler方法、方法體、方法簽名、注解
【Fail】在Spring和SpringMvc的配置Xml中增加、修改容器配置項(xiàng)。如
熱部署的本質(zhì),簡(jiǎn)單的理解,是在運(yùn)行中實(shí)時(shí)增加、替換JVM中的類文件而無需重啟JVM。
眾所周知,JVM使用ClassLoader加載類文件,內(nèi)含的雙親委派模型通過指定類文件加載的順序避免由于類沖突而導(dǎo)致核心類庫加載失敗。單個(gè)ClassLoader不能加載全限定名相同的類;不能修改已加載的類的聲明;不能卸載已加載的類,除非移除整個(gè)ClassLoader,或者被GC回收。
那么,修改原有的類(如Test.class)的任意元素后,熱部署就會(huì)面臨很多問題。比方說:
兩個(gè)全限定名相同的類如何加載?
類的實(shí)例化如何獲取到新的類?
更新類的聲明后,如增加類方法、實(shí)例方法;修改類方法、實(shí)例方法簽名、方法體、方法注解;新增、修改類變量、實(shí)例變量;修改接口、類的繼承關(guān)系,調(diào)用點(diǎn)怎么指向新的類?
如果JVM使用了內(nèi)聯(lián)優(yōu)化技術(shù)呢?
如何保證反射正確,比如調(diào)用Class的getName()、getMethods()、getField()等方法時(shí)如何獲取到新的類?
如果用了容器或者框架,修改JavaConfig或者XML后,怎么反映到容器里?
熱部署問題在底層繞不開ClassLoader,當(dāng)一個(gè)類被更新后,需要被重新載入到ClassLoader中,原先對(duì)類變量、實(shí)例變量、類方法、實(shí)例方法的調(diào)用都需要重定向到新類??梢酝ㄟ^引入一個(gè)包含所有符號(hào)鏈接的中間層,當(dāng)JVM加載用戶的類時(shí)進(jìn)行動(dòng)態(tài)增強(qiáng),并記錄下涉及的符號(hào)鏈接。
舉幾個(gè)實(shí)現(xiàn)思路的小例子:
在類加載時(shí)為新的類起一個(gè)新的限定名(如原來的類名是Test,而新的類名是Test_v1),繞開ClassLoader的限制。
所有指向老的類的符號(hào)鏈接都實(shí)時(shí)替換為相應(yīng)的新符號(hào)鏈接
在ClassLoader中查找老的類時(shí)返回新的類
監(jiān)控容器配置文件,發(fā)生變化后調(diào)用容器refresh API
ReferenceJava SE 6 新特性 Instrumentation 新功能
HotSwapAgent
深入探索 Java 熱部署
DCEVM
Get True Hot Swap in Java with DCEVM and IntelliJ IDEA
Features - JRebel
HotSwap和JRebel原理
實(shí)現(xiàn)增強(qiáng)的java class hotswap (三) 解決方案 續(xù)
實(shí)現(xiàn)增強(qiáng)的java class hotswap (三) 解決方案
Java是否可以做到修改類而不用重啟JVM?
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70435.html
摘要:效率專精系列善用統(tǒng)一描述語言提升開發(fā)效率分鐘搞定環(huán)境配置與使用考慮到篇幅較長(zhǎng)的文檔反復(fù)修改的情況,要快速找到修改點(diǎn)比較困難。 之前零零散散寫了幾篇文章,主要是實(shí)際開發(fā)過程中一些效率痛點(diǎn)和相應(yīng)的改善方法。今天抽空溫故知新,把之前的內(nèi)容串起來,做了個(gè)小總結(jié),即《效率專精系列》小系列的總集篇。 回顧項(xiàng)目開發(fā)流程 開發(fā)一個(gè)新項(xiàng)目時(shí),開發(fā)流程大概分成以下幾步: 設(shè)計(jì)方案,并落地成設(shè)計(jì)文檔 設(shè)計(jì)...
摘要:目前團(tuán)隊(duì)中前后端聯(lián)調(diào)是較之個(gè)人單獨(dú)開發(fā)相對(duì)耗時(shí)的一個(gè)環(huán)節(jié),主要體現(xiàn)在環(huán)境下的部署時(shí)間較長(zhǎng)。本文的目的是通過將聯(lián)調(diào)本地化,減少部分枯燥勞動(dòng)以及無效的等待時(shí)間,提高團(tuán)隊(duì)的開發(fā)效率。不需要更改的為外部,保持即可。 目前團(tuán)隊(duì)中前后端聯(lián)調(diào)是較之個(gè)人單獨(dú)開發(fā)相對(duì)耗時(shí)的一個(gè)環(huán)節(jié),主要體現(xiàn)在: beta環(huán)境下的部署時(shí)間較長(zhǎng)。首先部署beta需要經(jīng)過push分支、合并沖突、build、部署四個(gè)步驟。...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
閱讀 3698·2021-11-25 09:43
閱讀 2659·2021-11-25 09:43
閱讀 3857·2021-11-24 09:38
閱讀 704·2021-11-18 10:02
閱讀 2246·2021-09-22 15:53
閱讀 3007·2019-08-30 15:44
閱讀 2783·2019-08-30 14:01
閱讀 2769·2019-08-29 15:15