JAVA熱部署原理


1、熱部署是什么?

對於Java應用程序來說,熱部署就是在運行時更新Java類文件。
2、熱部署有什么用?
可以不重啟應用的情況下,更新應用。舉個例子,就像電腦可以在不重啟的情況下,更換U盤。
OSGI也正是因為它的模塊化和熱部署,才顯得熱門。
3、熱部署的原理是什么?
想要知道熱部署的原理,必須要了解java類的加載過程。一個java類文件到虛擬機里的對象,要經過如下過程。
首先通過java編譯器,將java文件編譯成class字節碼,類加載器讀取class字節碼,再將類轉化為實例,對實例newInstance就可以生成對象。
類加載器ClassLoader功能,也就是將class字節碼轉換到類的實例。
在java應用中,所有的實例都是由類加載器,加載而來。
一般在系統中,類的加載都是由系統自帶的類加載器完成,而且對於同一個全限定名的java類(如com.csiar.soc.HelloWorld),只能被加載一次,而且無法被卸載。
這個時候問題就來了,如果我們希望將java類卸載,並且替換更新版本的java類,該怎么做呢?
     既然在類加載器中,java類只能被加載一次,並且無法卸載。那是不是可以直接把類加載器給換了?答案是可以的,我們可以自定義類加載器,並重寫ClassLoader的findClass方法。想要實現熱部署可以分以下三個步驟:
1、銷毀該自定義ClassLoader
2、更新class類文件
3、創建新的ClassLoader去加載更新后的class類文件。
示例代碼如下:
 1 package com.csair.soc.hotswap;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 /**
 6  * 自定義類加載器,並override findClass方法
 7  */
 8 public class MyClassLoader extends ClassLoader{
 9      @Override
10      public Class<?> findClass(String name) throws ClassNotFoundException{
11             try{
12                 String fileName = name.substring(name.lastIndexOf("." )+1) + ".class" ;
13                 InputStream is = this.getClass().getResourceAsStream(fileName);
14                  byte[] b = new byte[is.available()];
15                 is.read(b);
16                  return defineClass(name, b, 0, b. length);
17            } catch(IOException e){
18                  throw new ClassNotFoundException(name);
19            }
20      }
21 }
需要更新的類文件:
1 package com.csair.soc.hotswap;
2 public class HelloWorld {
3      public void say(){
4            System. out.println( "Hello World V1");
5      }
6 }
在工程的根目錄下,生成V2版本的HelloWorld.class,內容如下。
1 package com.csair.soc.hotswap;
2 public class HelloWorld {
3       public void say(){
4            System. out.println( "Hello World V2");
5      }
6 }
測試主程序
 1 package com.csair.soc.hotswap;
 2 
 3 import java.io.File;
 4 import java.lang.reflect.Method;
 5 
 6 public class Hotswap {
 7      public static void main(String[] args) throws Exception {
 8             loadHelloWorld();
 9             // 回收資源,釋放HelloWorld.class文件,使之可以被替換
10            System. gc();
11            Thread. sleep(1000);// 等待資源被回收
12            File fileV2 = new File( "HelloWorld.class");
13            File fileV1 = new File(
14                       "bin\\com\\csair\\soc\\hotswap\\HelloWorld.class" );
15            fileV1.delete(); //刪除V1版本
16            fileV2.renameTo(fileV1); //更新V2版本
17            System. out.println( "Update success!");
18             loadHelloWorld();
19      }
20 
21      public static void loadHelloWorld() throws Exception {
22            MyClassLoader myLoader = new MyClassLoader(); //自定義類加載器
23            Class<?> class1 = myLoader
24                      .findClass( "com.csair.soc.hotswap.HelloWorld");//類實例
25            Object obj1 = class1.newInstance(); //生成新的對象
26            Method method = class1.getMethod( "say");
27            method.invoke(obj1); //執行方法say
28            System. out.println(obj1.getClass()); //對象
29            System. out.println(obj1.getClass().getClassLoader()); //對象的類加載器
30      }
31 }
輸出結果:
Hello World V1
class com.csair.soc.hotswap.HelloWorld
com.csair.soc.hotswap.MyClassLoader@bfc8e0
Update success!
Hello World V2
class com.csair.soc.hotswap.HelloWorld
com.csair.soc.hotswap.MyClassLoader@860d49
根據結果可以看到,在沒有重啟應用的情況下,成功的更新了HelloWorld類。
以上只是熱部署的最簡單的原理實踐,實際情況會復雜的多。OSGI的最關鍵理念就是應用模塊(bundle)化,對於每一個bundle,都有其自己的類加載器,當需要更新bundle時,把bundle和它的類加載器一起替換掉,就可以實現模塊的熱替換。


參考資料

深入理解java虛擬機
深入探討 Java 類加載器 http://www.ibm.com/developerworks/cn/java/j-lo-classloader/
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM