新的起點 新的開始

          快樂生活 !

          通過ClassLoader說明容器熱部署實現(xiàn)機制

              在J2EE的項目中,容器給我們提供的熱部署功能使得我們不用重啟動容器而修改我們的代碼。比如使用Weblogic,我們可以在Weblogic-application.xml中配置是否支持熱部署Servlet。查閱Weblogc 文檔,其實在Weblogic中,EJB組件也是可以熱部署的,但如何要熱部署EJB組件,Weblogc要求必須自定義ClassLoder。
              JVM規(guī)范中沒有指定JVM支持動態(tài)加載修改過的類。類的加載,卸載對于程序員是透明的。如果我們要實現(xiàn)類的動態(tài)加載我們就要理解JVM本身類的加載與卸載的原理,實現(xiàn)熱部署。對于JVM加載類方面的資料在網(wǎng)上很多的,在這里我做簡單概述:
              (1)JVM加載時通過ClassLoader加載的。
              (2)JVM有3層繼承關(guān)系的ClassLoder 分別是:
                                                 -----BootStrap類加載器 加載JRE/lib
                                                          -----------------ExtClassLoader 加載 JRE/lib/ext
                                                                     ----------AppClassLoader 加載ClassPath/
              (3)為了安全性,JVM加載采用了雙親委派機制,如何理解呢,就是當需要加載一個類時,當前的ClassLoader先請求父ClassLoader,依次
                類推,直到父類的ClassLoader無法加載時,才通過當前的ClassLoser加載,這就保證了像String這樣的類型必須使用JRE里面的, 使得
                JRE lib 下類不會被修改。同時避免了ClassCaseException。
             (4)在JVM中,一個實例是通過本身的類名+加載它的ClassLoader識別的,也就是說 不同的ClassLoader 加載同一個類在JVM是不同的。
             (5)同一個ClassLoader是不允許多次加載一個類的,否則會報java.lang.LinkageError。attempted  duplicate class definition for
                 name XXX,在下面的例子中會指出。
              既然JVM不支持熱部署,那么要實現(xiàn)熱部署,就必須自定義ClassLoader,當類被修改過后,加載該類。下面通過代碼說明:
          package classloader;

          /**
           * 
          @author vma
           
          */
          // 自定義一個類加載器
          public class DynamicClassLoader extends ClassLoader {
              
            
              
          public Class<?> findClass(byte[] b) throws ClassNotFoundException {

                  
          return defineClass(null, b, 0, b.length);
              }


          package classloader;
          import java.io.File;
          import java.io.FileInputStream;
          import java.io.IOException;
          /**
           * 
          @author vma
           
          */
          public class ManageClassLoader {
              DynamicClassLoader dc 
          =null;
              
              Long lastModified 
          = 0l;
              Class c 
          = null;
              //加載類, 如果類文件修改過加載,如果沒有修改,返回當前的
              
          public Class loadClass(String name) throws ClassNotFoundException, IOException{
               
          if (isClassModified(name)){
                  dc 
          =  new DynamicClassLoader();
                
          return c = dc.findClass(getBytes(name));
               }
               
          return c;
              }
              //判斷是否被修改過
              
          private boolean isClassModified(String filename) {
                  
          boolean returnValue = false;
                  File file 
          = new File(filename);
                  
          if (file.lastModified() > lastModified) {
                      returnValue 
          = true;
                  }
                  
          return returnValue;
              }
                 // 從本地讀取文件
                 
          private byte[] getBytes(String filename) throws IOException {
                  File file 
          = new File(filename);
                  
          long len = file.length();
                  lastModified 
          = file.lastModified();
                  
          byte raw[] = new byte[(int) len];
                  FileInputStream fin 
          = new FileInputStream(file);
                  
          int r = fin.read(raw);
                  
          if (r != len) {
                      
          throw new IOException("Can't read all, " + r + " != " + len);
                  }
                  fin.close();
                  
          return raw;
              }
          }
          測試類;Main 每隔 5s 加載一次

          package classloader;

          import java.io.IOException;
          import java.lang.reflect.InvocationTargetException;
          import java.lang.reflect.Method;

          /**
           *
           * 
          @author vma
           
          */
          public class Main {

              
          /**
               * 
          @param args the command line arguments
               
          */
              
          public static void main(String[] args) throws ClassNotFoundException, IOException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException, InterruptedException {
                  String path 
          = "D:\\deploy\\JDBC\\ClassLoader\\build\\classes\\classloader\\LocalClass.class";
                  ManageClassLoader mc 
          = new ManageClassLoader();
                  
          while(true){
                 Class c 
          = mc.loadClass(path);
                  Object o 
          = c.newInstance();
                 Method m 
          = c.getMethod("getName");
                  m.invoke(o);
                  System.out.println(c.getClassLoader());
                  Thread.sleep(
          5000);
                  }


              }

          被加載的類
          /**
           *
           * 
          @author vma
           
          */
          public class LocalClass {

              
          public void getName() {
                  
                System.out.println(
          "hahaha ");
              }
          }

          運行時,每隔5s 輸出:
          hahaha
          classloader.DynamicClassLoader@61de33
          當我們修改 System.out.println("hahaha "); ---> System.out.println("changed  "); 編譯LocalClass后
          輸出變?yōu)椋?br /> changed
          classloader.DynamicClassLoader@173a10f

          loadClass中, 我們必須重新初始化一個ClassLoader,負責就會違背同一個ClassLoader是不允許多次加載一個類的。
              public Class loadClass(String name) throws ClassNotFoundException, IOException{
               
          if (isClassModified(name)){
                  dc 
          =  new DynamicClassLoader();
                
          return c = dc.findClass(getBytes(name));
               }
               
          return c;
              }

          當然,容器的實現(xiàn)機制肯定及其完善,不可能周期性的加載,可能回通過監(jiān)聽機制,動態(tài)加載修改過的類。但它的實現(xiàn)機制肯定也是重新
          實例化一個ClassLoder,加載需要加載的類。






           



          posted on 2008-08-30 23:36 advincenting 閱讀(11493) 評論(8)  編輯  收藏

          評論

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-08-31 12:11 尋道者

          好。  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-08-31 20:55 BeanSoft

          收藏了!  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-09-01 08:59 藍劍

          很好,收藏!謝謝  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-09-01 09:51 CowNew開源團隊

          最近一年一直在搞.net的東西,.net里連一個熱加載機制都不支持,微軟還一大堆借口,好懷念Java。  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-09-03 09:54 usomething

          兄弟,想問一句,你的classLoader支不支持加載修改后的jar?  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-09-03 14:12 advincenting

          在這里,我僅僅是舉例子來說明如何熱部署,你當然可以定制一個Jar的加載類,動態(tài)加載卸載就可以了。  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-10-08 10:54 freeman

          樓主,我有個問題,假如LocalClass里面又引用了其它的類如Person類
          那我們就必須先加載Person類,再加載LocalClass,這樣new LocalClass的時候才不會出錯,我的問題是自己定義的Classloader為什么不會自動加載Person類呢?
          public class LocalClass {

          public void getName() {
          Person person =new Person();
          person.setName("freeman");
          System.out.println("hahaha ---------++-----"+person.getName());
          }
          }  回復  更多評論   

          # re: 通過ClassLoader說明容器熱部署實現(xiàn)機制 2008-10-09 09:26 freeman

          上面的問題,我自己解決了,是因為我程序里寫的有問題,結(jié)果Person類沒有加載進去的原因,只要在用LocalClass之前把Person類加載進來就行了。

          但我現(xiàn)在又遇到新問題了,就是如果LocalClass 如果繼承某個父類,那父類一定要在LocalClass之前加載,如何能解決這個限制啊,我想達到,只要在用LocalClass類實例對象之前加載了相關(guān)類就行了,不要一定非要我手功指定順序加載,那位帥哥搞過啊!!  回復  更多評論   


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           

          公告

          Locations of visitors to this pageBlogJava
        1. 首頁
        2. 新隨筆
        3. 聯(lián)系
        4. 聚合
        5. 管理
        6. <2008年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統(tǒng)計

          常用鏈接

          留言簿(13)

          隨筆分類(71)

          隨筆檔案(179)

          文章檔案(13)

          新聞分類

          IT人的英語學習網(wǎng)站

          JAVA站點

          優(yōu)秀個人博客鏈接

          官網(wǎng)學習站點

          生活工作站點

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 柳江县| 牙克石市| 梁河县| 丰台区| 玛曲县| 象山县| 黄梅县| 金寨县| 沅江市| 郓城县| 古交市| 库伦旗| 新和县| 思茅市| 黄龙县| 康定县| 婺源县| 永和县| 合作市| 成武县| 武强县| 邵阳市| 开原市| 日土县| 临江市| 大理市| 曲麻莱县| 双牌县| 塘沽区| 长宁区| 新龙县| 阳西县| 温宿县| 腾冲县| 静宁县| 桐梓县| 万安县| 万载县| 桓仁| 息烽县| 潼南县|