05.29 這20行代碼讓你瞭解java熱加載功能的核心原理

目的

這是面試/工作中都能用到的知識,花幾分鐘的時間,通過精簡的代碼,帶你掌握java中熱加載的實現方式以及核心原理。(我是在看JVM類加載機制和Tomcat源碼的時候受到啟發)

準備工作

1、 在D:\\\\test-class\\\\目錄,寫一個類 HelloService.java

public class HelloService {

public String getValue() {

return "666";

}

}

2、 編譯

javac HelloService.java

現在我們在D:\\\\test-class\\\\目錄已經有了一個HelloService.class。

接下來,我們實現這個類的熱加載,每次更新這個代碼,都能不停機,自動加載最新代碼邏輯。

熱加載核心代碼

這20行代碼讓你瞭解java熱加載功能的核心原理

核心代碼

描述一下這段代碼運行的效果,運行之後,每隔1秒去加載最新的class文件,調用上述HelloService的getValue方法。不斷輸出

調用getValue獲得的返回值為:666

調用getValue獲得的返回值為:666

調用getValue獲得的返回值為:666

不要關閉這個程序,我們來測試熱加載

  • 將HelloService.java中getValue方法的返回值修改為 【return "999";】
  • javac 重新編譯 HelloService.java
  • 編譯成功後,你應該會看到程序的控制檯輸出變為 “調用getValue獲得的返回值為:999”
  • 如果輸出內容改變了,則代表熱加載成功。

是不是很神奇,接下來介紹一下原理

原理分解

1、 首要了解類加載器是什麼

我們的代碼由.java 編譯成 .class,要想在jvm中運行,需要被加載到JVM中。

而加載class的工作是有類加載器實例去實現的,類加載器支持通過文件目錄,jar,zip,網絡等多種途徑,加載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中有這麼一個概念“同一個類名,同一個類加載器實例加載的,代表是同一個類”。

如果我們要自己實現業務代碼的熱加載,就不能用默認的類加載器實例,因為同一個類加載器實例加載一次後會存起來,後面的class文件就算更新了也不會再次加載了。

我們需要自己創建類加載器實例,告訴它我們要加載的class文件位置。我上面的代碼中每隔一秒創建一個URLClassLoader類加載器實例對象,用這個新的類加載器實例去加載修改後的class,所以jvm會認為這是一個新的類,從而實現了熱更新。

這就是利用了JVM類加載機制實現的熱加載,比如Tomcat中jsp熱更新就是這樣實現的。

你懂了嘛?有什麼想法可以留言交流哦!

這20行代碼讓你瞭解java熱加載功能的核心原理

JVM類加載還有其他知識(比如雙親委派?)關注我後續分享


分享到:


相關文章: