1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      Java基于自定義類加載器如何實(shí)現(xiàn)熱部署

      這篇文章主要介紹Java基于自定義類加載器如何實(shí)現(xiàn)熱部署,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

      目前創(chuàng)新互聯(lián)已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、淳安網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

      熱部署:

      熱部署就是在不重啟應(yīng)用的情況下,當(dāng)類的定義即字節(jié)碼文件修改后,能夠替換該Class創(chuàng)建的對象。一般情況下,類的加載都是由系統(tǒng)自帶的類加載器完成,且對于同一個(gè)全限定名的java類,只能被加載一次,而且無法被卸載。可以使用自定義的 ClassLoader 替換系統(tǒng)的加載器,創(chuàng)建一個(gè)新的 ClassLoader,再用它加載 Class,得到的 Class 對象就是新的(因?yàn)椴皇峭粋€(gè)類加載器),再用該 Class 對象創(chuàng)建一個(gè)實(shí)例,從而實(shí)現(xiàn)動(dòng)態(tài)更新。如:修改 JSP 文件即生效,就是利用自定義的 ClassLoader 實(shí)現(xiàn)的。

      還需要?jiǎng)?chuàng)建一個(gè)守護(hù)線程,不斷地檢查class文件是否被修改過,通過判斷文件的上次修改時(shí)間實(shí)現(xiàn)。

      演示:

      原來的程序:

      Java基于自定義類加載器如何實(shí)現(xiàn)熱部署

      修改后重新編譯:

      Java基于自定義類加載器如何實(shí)現(xiàn)熱部署

      代碼:

      package Dynamic;
       
      import java.io.*;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.util.concurrent.TimeUnit;
       
      public class ClassLoadStudy {
        public static void main(String[] args) throws Exception {
          HotDeploy hot = new HotDeploy("Dynamic.Task");
          hot.monitor();
          while (true) {
            TimeUnit.SECONDS.sleep(2);
            hot.getTask().run();
          }
        }
      }
       
      // 熱部署
       
      class HotDeploy {
        private static volatile Runnable instance;
        private final String FILE_NAME;
        private final String CLASS_NAME;
       
        public HotDeploy(String name) {
          CLASS_NAME = name; // 類的完全限定名
          name = name.replaceAll("\\.", "/") + ".class";
          FILE_NAME = (getClass().getResource("/") + name).substring(6); // 判斷class文件修改時(shí)間使用,substring(6)去掉開頭的file:/
        }
       
        // 獲取一個(gè)任務(wù)
        public Runnable getTask() {
          if (instance == null) { // 雙重檢查鎖,單例,線程安全
            synchronized (HotDeploy.class) {
              if (instance == null) {
                try {
                  instance = createTask();
                } catch (Exception e) {
                  e.printStackTrace();
                }
              }
            }
          }
          return instance;
        }
       
        // 創(chuàng)建一個(gè)任務(wù),重新加載 class 文件
        private Runnable createTask() {
          try {
            Class clazz = MyClassLoader.getLoader().loadClass(CLASS_NAME);
            if (clazz != null)
              return (Runnable)clazz.newInstance();
          } catch (Exception e) {
            e.printStackTrace();
          }
          return null;
        }
       
       
        // 監(jiān)視器,監(jiān)視class文件是否被修改過,如果是的話,則重新加載
        public void monitor() throws IOException {
          Thread t = new Thread(()->{
            try {
              long lastModified = Files.getLastModifiedTime(Path.of(FILE_NAME)).toMillis();
              while(true) {
                Thread.sleep(500);
                long now = Files.getLastModifiedTime(Path.of(FILE_NAME)).toMillis();
                if(now != lastModified) { // 如果class文件被修改過了
                  lastModified = now;
                  instance = createTask(); // 重新加載
                }
              }
            } catch (InterruptedException | IOException e) {
              e.printStackTrace();
            }
          });
          t.setDaemon(true); // 守護(hù)線程
          t.start();
        }
      }
       
      // 自定義的類加載器
      class MyClassLoader extends ClassLoader {
        @Override
        public Class findClass(String name) throws ClassNotFoundException {
          try {
            String fileName = "/" + name.replaceAll("\\.", "/") + ".class";
            InputStream is = getClass().getResourceAsStream(fileName);
            byte[] b = is.readAllBytes();
            return defineClass(name, b, 0, b.length);
          } catch (IOException e) {
            throw new ClassNotFoundException(name);
          }
        }
        public static MyClassLoader getLoader() {
          return new MyClassLoader();
        }
      }

      遇到的坑:

      剛開始自定義類加載器時(shí),重寫的是 loadClass(String name) 方法,但不斷地報(bào)錯(cuò),后來明白了,因?yàn)?Task 類實(shí)現(xiàn)了 Java.lang.Runnable 接口,且重寫 loadClass 方法破壞了雙親委派機(jī)制,導(dǎo)致了自定義的類加載器去加載 java.lang.Runnable,但被Java安全機(jī)制禁止了所以會(huì)報(bào)錯(cuò)。defineClass調(diào)用preDefineClass,preDefineClass 會(huì)檢查包名,如果以java開頭,就會(huì)拋出異常,因?yàn)樽層脩糇远x的類加載器來加載Java自帶的類庫會(huì)引起混亂。

      于是又重寫findClass 方法,但還是不行,findClass方法總是得不到執(zhí)行,因?yàn)榫幾g好的類是在 classpath 下的,而自定義的 ClassLoader 的父加載器是 AppClassLoader,由于雙親委派機(jī)制,類就會(huì)被 Application ClassLoader來加載了。因此自定義的 findClass 方法就不會(huì)被執(zhí)行。解決方法是,向構(gòu)造器 ClassLoader(ClassLoader parent) 傳入null,或傳入 getSystemClassLoader().getParent()。

      還有就是路徑問題:

      • path不以 / 開頭時(shí),默認(rèn)是從此類所在的包下取資源;path 以 / 開頭時(shí),則是從ClassPath根下獲取;

        • URL getClass.getResource(String path)

        • InputStream getClass().getResourceAsStream(String path)

        • getResource("") 返回當(dāng)前類所在的包的路徑

        • getResource("/") 返回當(dāng)前的 classpath 根據(jù)路徑

      • path 不能以 / 開始,path 是從 classpath 根開始算的, 因?yàn)閏lassloader 不是用戶自定義的類,所以沒有相對路徑的配置文件可以獲取,所以默認(rèn)都是從哪個(gè)classpath 路徑下讀取,自然就沒有必要以 / 開頭了 。

        • URL Class.getClassLoader().getResource(String path)

        • InputStream Class.getClassLoader().getResourceAsStream(String path)

      Java是什么

      Java是一門面向?qū)ο缶幊陶Z言,可以編寫桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序。

      以上是“Java基于自定義類加載器如何實(shí)現(xiàn)熱部署”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


      文章標(biāo)題:Java基于自定義類加載器如何實(shí)現(xiàn)熱部署
      網(wǎng)頁鏈接:http://www.ef60e0e.cn/article/jejpgp.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        望江县| 滕州市| 东乌珠穆沁旗| 武鸣县| 卓资县| 土默特左旗| 惠安县| 山东| 高密市| 岑巩县| 潞西市| 信阳市| 阜平县| 黔南| 金华市| 泸水县| 萍乡市| 鄂尔多斯市| 白河县| 沾化县| 肃南| 江北区| 张家港市| 白玉县| 和平县| 邛崃市| 栖霞市| 隆林| 罗甸县| 香港| 淮阳县| 巩留县| 永安市| 聊城市| 招远市| 江津市| 鄢陵县| 沅陵县| 方正县| 三穗县| 紫阳县|