idea的熱加載怎麼實現的?

本將軍久居山海關


1. 題主說的IDEA 熱加載是什麼?


  • 在IDEA中開發WEB項目時,IDEA的 發佈按鈕帶來的熱加載
  • IDEA插件帶來的熱加載
注意:熱加載 熱部署 熱更新 實際上是一個概念,下文中會混用。

2. 簡單解釋下這兩種形式

1)IDEA在開發WEB項目時,熱部署按鈕的或者啟動按鈕的四個選項,如圖

事實上,IDEA通過tomcat運行項目時需要指定tomcat的home目錄,然後啟動時IDEA會運行

catlina.bat

並指定上下文配置目錄,web根目錄(就是項目)。配置和web下項目會發布到IDEA的配置文件夾中。具體路徑如下:

Using CATALINA_BASE: "C:\\Users\\用戶名\\.IntelliJIdea2018.2(IDEA配置目錄)\\system\\tomcat\\Unnamed_項目名"
Using CATALINA_HOME: "D:\\MySoft\\apache-tomcat-8.5.29"
Using CATALINA_TMPDIR: "D:\\MySoft\\apache-tomcat-8.5.29\\temp"
Using JRE_HOME: "D:\\MySoft\\Java\\jdk1.8.0_171"
Using CLASSPATH: "D:\\MySoft\\apache-tomcat-8.5.29\\bin\\bootstrap.jar;D:\\MySoft\\apache-tomcat-8.5.29\\bin\\tomcat-juli.jar"

其實和將war包放入tomcat的webapp目錄,沒有任何功能上的區別!

資源文件和class的熱更新就是文件替換!而java class的熱加載,是tomcat(滿足servlet標準的web容器都支持)自身的功能。

在tomcat

server.xml

中可以自己指定 autoDeploy="true" 是否開關,如果關閉,就不支持熱部署了。每次修改class都需要重啟,但是修改資源文件不需要,因為資源文件不用加載到內存中,只是需要時才加載。


上圖四個選項:1.update resources 更新變動的資源文件 2. update classes and resources 更新變動的class和資源文件 3. redeploy class和資源文件全部更新 4. 重啟tomcat


另外:

eclipse和idea在部署web應用這一塊做法幾乎完全相同,但是一些配置行為不同,並且部署的目錄在工作空間的

.metadata

裡。


2. IDEA插件帶來的熱加載

1)Settings->Build project automatically

這個設置就是將class自動編譯到普通項目的bin目錄,或者maven項目的target目錄中,不論從外部servlet容器還是嵌入式容器,只要啟動就需要tomcat、jetty等servlet容器開啟熱部署,如果沒有開起,依然不能使用熱部署。

2)spring-boot-devtools

這個是springboot項目中使用的插件,在項目啟動後,會默認啟動一個線程,監視工作空間或者target中,發生文件改動就即時更新。


3. 簡單闡述原理

資源文件都是在需要時讀取,所以熱更新直接就能替換,主要是java類的熱更新。

雙親委派機制
雙親委派模型的過程是:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個 類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請 求最終都應該傳送到頂層的啟動類加載器中,只有當父加載器反饋自己無法完全這個加載請求時,子 加載器才會嘗試自己去加載。 (某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給 父類加載器,依次遞歸,如果父類加載器可以完成類加載任務,就成功返回;只有父類加載器無法完 成此加載任務時,才自己去加載。)
沙箱機制
沙箱機制是由基於雙親委派機制上 採取的一種JVM的自我保護機制,假設你要寫一個java.lang.String 的類,由於雙親委派機制的原理,此請求會先交給Bootstrap試圖進行加載,但是Bootstrap在加載類時首 先通過包和類名查找rt.jar中有沒有該類,有則優先加載rt.jar包中的類,因此就保證了java的運行機制不 會被破壞.
雙親委派機制+沙箱機制(防止惡意代碼對java的破壞
Java類加載器種類
1. Bootstrap類加載器 - $JAVA_HOME/jre/lib/rt.jar
2. Ext類加載器 - $JAVA_HOME/jre/lib/ext/*.jar
3. System(或者AppClassLoader)類加載器 - $CLASSPATH
AppClassLoader 應用類加載器在最下面,中間是 ExtClassLoader拓展類加載器,最上面是BootstrapClassLoader 啟動類加載器。(三者之 間是父子關係)
上面還有一點,就是類加載器都是sun.misc.Launcher開頭的,sun.misc.Launcher它是一個java虛 擬機的入口應用


上面說的只是說,系統類不能被冒充,但是還是能再次加載的!(網上所有說,例如可以在自己的項目裡簡歷

java.lang.String

能替換jdk的String的,都是錯誤的)

也就是說,我們要實現熱更新、熱部署、熱加載,只要實現自己的類加載器,去約定好的路徑加載class,就完全能實現自己的熱部署插件!


4. 解決問題

idea的熱加載怎麼實現的?
java雙親委派機制,一個類已經加載,還能重新加載覆蓋嗎?如不能是怎麼實現熱加載

IDEA的熱加載是通過複製文件到tomcat的映射webapp中,讓tomcat自動部署,或者是springboot項目發佈文件到target目錄中,讓嵌入式serlvet容器自動部署,究其原理是Java語言的類加載機制(類加載機制會使用雙親委派原則) 。

一個類被加載到內存中,能夠被覆蓋。


結束。


分享到:


相關文章: