亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

Java基于自定義類加載器實現熱部署過程解析

瀏覽:2日期:2022-09-04 15:12:59

熱部署:

熱部署就是在不重啟應用的情況下,當類的定義即字節碼文件修改后,能夠替換該Class創建的對象。一般情況下,類的加載都是由系統自帶的類加載器完成,且對于同一個全限定名的java類,只能被加載一次,而且無法被卸載。可以使用自定義的 ClassLoader 替換系統的加載器,創建一個新的 ClassLoader,再用它加載 Class,得到的 Class 對象就是新的(因為不是同一個類加載器),再用該 Class 對象創建一個實例,從而實現動態更新。如:修改 JSP 文件即生效,就是利用自定義的 ClassLoader 實現的。

還需要創建一個守護線程,不斷地檢查class文件是否被修改過,通過判斷文件的上次修改時間實現。

演示:

原來的程序:

Java基于自定義類加載器實現熱部署過程解析

修改后重新編譯:

Java基于自定義類加載器實現熱部署過程解析

代碼:

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文件修改時間使用,substring(6)去掉開頭的file:/ } // 獲取一個任務 public Runnable getTask() { if (instance == null) { // 雙重檢查鎖,單例,線程安全 synchronized (HotDeploy.class) {if (instance == null) { try { instance = createTask(); } catch (Exception e) { e.printStackTrace(); }} } } return instance; } // 創建一個任務,重新加載 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; } // 監視器,監視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); // 守護線程 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(); }}

遇到的坑:

剛開始自定義類加載器時,重寫的是 loadClass(String name) 方法,但不斷地報錯,后來明白了,因為 Task 類實現了 Java.lang.Runnable 接口,且重寫 loadClass 方法破壞了雙親委派機制,導致了自定義的類加載器去加載 java.lang.Runnable,但被Java安全機制禁止了所以會報錯。defineClass調用preDefineClass,preDefineClass 會檢查包名,如果以java開頭,就會拋出異常,因為讓用戶自定義的類加載器來加載Java自帶的類庫會引起混亂。

于是又重寫findClass 方法,但還是不行,findClass方法總是得不到執行,因為編譯好的類是在 classpath 下的,而自定義的 ClassLoader 的父加載器是 AppClassLoader,由于雙親委派機制,類就會被 Application ClassLoader來加載了。因此自定義的 findClass 方法就不會被執行。解決方法是,向構造器 ClassLoader(ClassLoader parent) 傳入null,或傳入 getSystemClassLoader().getParent()。

還有就是路徑問題:

path不以 / 開頭時,默認是從此類所在的包下取資源;path 以 / 開頭時,則是從ClassPath根下獲取; URL getClass.getResource(String path) InputStream getClass().getResourceAsStream(String path) getResource('') 返回當前類所在的包的路徑 getResource('/') 返回當前的 classpath 根據路徑 path 不能以 / 開始,path 是從 classpath 根開始算的, 因為classloader 不是用戶自定義的類,所以沒有相對路徑的配置文件可以獲取,所以默認都是從哪個classpath 路徑下讀取,自然就沒有必要以 / 開頭了 。 URL Class.getClassLoader().getResource(String path) InputStream Class.getClassLoader().getResourceAsStream(String path)

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
主站蜘蛛池模板: 91丝瓜视频最新版 | 国产99久久精品一区二区 | 黄色大片在线免费观看 | 蛇女欲潮三级在线看 | 国产亚洲精品成人一区看片 | 一级做a爱片特黄在线观看 一级做a爱片特黄在线观看免费看 | 亚洲啪啪网址 | 亚洲七七久久精品中文国产 | 欧美高清夜夜片a | 欧美成片vs欧美 | 看成年全黄大色黄大片 | 一级特级欧美aaaaa毛片 | 麻豆网站在线 | 成在线人免费视频一区二区三区 | 色综合色综合色综合色综合 | 中国一级毛片欧美一级毛片 | 亚洲 欧美 国产另类首页 | 1024毛片| 国产精品一区二区三区免费 | 亚洲一区二区三区高清 | 亚洲成网站www久久九 | 久久人人精品 | 国产精品亚洲综合 | 91网视频| 一级做a爱过程免费视频麻豆 | 亚洲精品一区二区中文 | 91老女人 | 美国黑人特大一级毛片 | 国产精品第1页 | 九九久久国产精品 | 欧美特黄aaaaaa | 边吃奶边弄进去男女视频 | 2级毛片 | 国产毛片一区二区 | 极品美女国产精品免费一区 | 国产在线观看xxxx免费 | 久久久久夜色精品波多野结衣 | 欧美成人午夜影院 | 日本高清视频一区二区 | 日本一级免费 | 亚洲欧美日韩中文综合v日本 |