這是面試/工作中都能用到的知識箍土,花幾分鐘的時間,通過精簡的代碼,帶你掌握java中熱加載的實現(xiàn)方式以及核心原理负乡。(我是在看JVM類加載機制和Tomcat源碼的時候受到啟發(fā))
準備工作
1榜田、 在D:\test-class\目錄益兄,寫一個類 HelloService.java
public class HelloService {
public String getValue() {
return "666";
}
}
2、 編譯
javac HelloService.java
現(xiàn)在我們在D:\test-class\目錄已經(jīng)有了一個HelloService.class箭券。
接下來净捅,我們實現(xiàn)這個類的熱加載,每次更新這個代碼辩块,都能不停機蛔六,自動加載最新代碼邏輯荆永。
熱加載核心代碼
這20行代碼讓你了解java熱加載功能的核心原理
核心代碼
描述一下這段代碼運行的效果,運行之后国章,每隔1秒去加載最新的class文件屁魏,調用上述HelloService的getValue方法。不斷輸出
調用getValue獲得的返回值為:666
編推薦一個學Java的學習裙【六七八捉腥,二四一氓拼,五六三】,無論你是大牛還是小白抵碟,是想轉行還是想入行都可以來了解一起進步一起學習桃漾!裙內有開發(fā)工具,很多干貨和技術資料分享我們來測試熱加載
不要關閉這個程序拟逮,
將HelloService.java中getValue方法的返回值修改為 【return "999";】
javac 重新編譯 HelloService.java
編譯成功后撬统,你應該會看到程序的控制臺輸出變?yōu)?“調用getValue獲得的返回值為:999”
如果輸出內容改變了,則代表熱加載成功敦迄。
是不是很神奇恋追,接下來介紹一下原理
原理分解
1、 首要了解類加載器是什么
我們的代碼由.java 編譯成 .class罚屋,要想在jvm中運行苦囱,需要被加載到JVM中。
而加載class的工作是有類加載器實例去實現(xiàn)的脾猛,類加載器支持通過文件目錄撕彤,jar,zip猛拴,網(wǎng)絡等多種途徑羹铅,加載class類文件。
JVM啟動后就默認有三個類加載器實例愉昆,負責去加載不同位置的class职员。
> 核心類庫加載器 BootStrap ClassLoader,負責加載jdk安裝目錄下lib文件夾里面的jar包跛溉,我們的String.class焊切,System.class這些類都放在這個目錄下面,啟動jvm就會去加載倒谷,必不可少蛛蒙。
> 拓展類庫加載器 Extension ClassLoader糙箍,負責加載jdk安裝目錄下lib/ext文件夾里面的jar包渤愁,這里面是一些jdk的拓展jar包,比如zipfs.jar這樣的包或工具類深夯。拓展的意思就是在某些情況下抖格,這些jar包不加載也不影響jvm工作诺苹。
> 應用程序代碼加載器 Application ClassLoader,負責加載我們自己寫的程序代碼雹拄,通過java命令 -cp 或者 -classpath告訴jvm我們的代碼class存放位置收奔。如果我們的程序是jar包運行,你可以在jar包 META-INF目錄MANIFEST.MF文件里面看到一個Class-Path: .配置滓玖,這就是指定代碼位置的坪哄。
2、 熱加載
java中有這么一個概念“同一個類名势篡,同一個類加載器實例加載的翩肌,代表是同一個類”。
如果我們要自己實現(xiàn)業(yè)務代碼的熱加載禁悠,就不能用默認的類加載器實例念祭,因為同一個類加載器實例加載一次后會存起來,后面的class文件就算更新了也不會再次加載了碍侦。
我們需要自己創(chuàng)建類加載器實例粱坤,告訴它我們要加載的class文件位置。我上面的代碼中每隔一秒創(chuàng)建一個URLClassLoader類加載器實例對象瓷产,用這個新的類加載器實例去加載修改后的class站玄,所以jvm會認為這是一個新的類,從而實現(xiàn)了熱更新濒旦。
這就是利用了JVM類加載機制實現(xiàn)的熱加載蜒什,比如Tomcat中jsp熱更新就是這樣實現(xiàn)的。