<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    新的起點 新的開始

    快樂生活 !

    通過ClassLoader說明容器熱部署實現機制

        在J2EE的項目中,容器給我們提供的熱部署功能使得我們不用重啟動容器而修改我們的代碼。比如使用Weblogic,我們可以在Weblogic-application.xml中配置是否支持熱部署Servlet。查閱Weblogc 文檔,其實在Weblogic中,EJB組件也是可以熱部署的,但如何要熱部署EJB組件,Weblogc要求必須自定義ClassLoder。
        JVM規范中沒有指定JVM支持動態加載修改過的類。類的加載,卸載對于程序員是透明的。如果我們要實現類的動態加載我們就要理解JVM本身類的加載與卸載的原理,實現熱部署。對于JVM加載類方面的資料在網上很多的,在這里我做簡單概述:
        (1)JVM加載時通過ClassLoader加載的。
        (2)JVM有3層繼承關系的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不支持熱部署,那么要實現熱部署,就必須自定義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后
    輸出變為:
    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;
        }

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






     



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

    評論

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

    好。  回復  更多評論   

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

    收藏了!  回復  更多評論   

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

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

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

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

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

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

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

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

    # re: 通過ClassLoader說明容器熱部署實現機制 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說明容器熱部署實現機制 2008-10-09 09:26 freeman

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

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


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


    網站導航:
     

    公告

    Locations of visitors to this pageBlogJava
  • 首頁
  • 新隨筆
  • 聯系
  • 聚合
  • 管理
  • <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    統計

    常用鏈接

    留言簿(13)

    隨筆分類(71)

    隨筆檔案(179)

    文章檔案(13)

    新聞分類

    IT人的英語學習網站

    JAVA站點

    優秀個人博客鏈接

    官網學習站點

    生活工作站點

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲欧洲∨国产一区二区三区 | 91免费资源网站入口| 亚洲欧洲日产国码无码网站 | 国产三级电影免费观看| 亚洲午夜理论片在线观看| 成人毛片免费视频| 亚洲精品无码成人| 免费成人黄色大片| 久久99久久成人免费播放| 亚洲国产精品成人久久| 日韩中文字幕免费视频| 亚洲欧洲日产国码www| 成年女人免费碰碰视频| 国产亚洲女在线线精品| 国产精品亚洲产品一区二区三区 | 四虎在线成人免费网站| 国产精品高清视亚洲一区二区| 四虎成人免费观看在线网址| 精品亚洲成A人在线观看青青 | 亚洲无线电影官网| 日本免费一区二区在线观看| 亚洲熟妇无码av另类vr影视| 国产高清在线免费视频| 丰满少妇作爱视频免费观看| 亚洲成亚洲乱码一二三四区软件| 亚洲人成在线免费观看| 亚洲精华液一二三产区| 国产亚洲精品AA片在线观看不加载| 小日子的在线观看免费| 亚洲综合无码无在线观看| 亚洲成av人片不卡无码久久| 在线播放免费人成毛片乱码| 色偷偷亚洲女人天堂观看欧| 亚洲视频在线免费| 1000部夫妻午夜免费| 国产亚洲精彩视频| 亚洲视频在线观看一区| 国产片免费在线观看| 91视频免费观看| 一本天堂ⅴ无码亚洲道久久| 亚洲精品自在在线观看|