1. 程式人生 > >Java Class的熱替換 自定義ClassLoader載入.class(java熱部署實現 )

Java Class的熱替換 自定義ClassLoader載入.class(java熱部署實現 )

本文是java熱替換的實驗,參考了 之前的錯誤是,沒有整合ClassLoader,而是直接使用了
  1. classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();  
這個語句只適用於載入.jar 如果載入.class的話需要使用自定義的ClassLoader

  1. package yerasel;  
  2. import java.io.BufferedReader;  
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.InputStreamReader;  
  9. import java.lang.reflect.Field;  
  10. import java.lang.reflect.InvocationTargetException;  
  11. import java.lang.reflect.Method;  
  12. import java.net.MalformedURLException;  
  13. import java.net.URL;  
  14. import java.net.URLClassLoader;  
  15. import java.util.HashSet;  
  16. /* 
  17.  *  實現熱部署,自定義ClassLoader,載入的是.class 
  18.  */
  19. class HowswapCL extends ClassLoader {  
  20.     private String basedir; // 需要該類載入器直接載入的類檔案的基目錄
  21.     private HashSet dynaclazns; // 需要由該類載入器直接載入的類名
  22.     public HowswapCL(String basedir, String[] clazns) {  
  23.         super(null); // 指定父類載入器為 null
  24.         this.basedir = basedir;  
  25.         dynaclazns = new HashSet();  
  26.         loadClassByMe(clazns);  
  27.     }  
  28.     privatevoid loadClassByMe(String[] clazns) {  
  29.         for (int i = 0; i < clazns.length; i++) {  
  30.             loadDirectly(clazns[i]);  
  31.             dynaclazns.add(clazns[i]);  
  32.         }  
  33.     }  
  34.     private Class loadDirectly(String name) {  
  35.         Class cls = null;  
  36.         StringBuffer sb = new StringBuffer(basedir);  
  37.         String classname = name.replace('.', File.separatorChar) + ".class";  
  38.         sb.append(File.separator + classname);  
  39.         File classF = new File(sb.toString());  
  40.         try {  
  41.             cls = instantiateClass(name, new FileInputStream(classF),  
  42.                     classF.length());  
  43.         } catch (FileNotFoundException e) {  
  44.             // TODO Auto-generated catch block
  45.             e.printStackTrace();  
  46.         }  
  47.         return cls;  
  48.     }  
  49.     private Class instantiateClass(String name, InputStream fin, long len) {  
  50.         byte[] raw = newbyte[(int) len];  
  51.         try {  
  52.             fin.read(raw);  
  53.             fin.close();  
  54.         } catch (IOException e) {  
  55.             // TODO Auto-generated catch block
  56.             e.printStackTrace();  
  57.         }  
  58.         return defineClass(name, raw, 0, raw.length);  
  59.     }  
  60.     protected Class loadClass(String name, boolean resolve)  
  61.             throws ClassNotFoundException {  
  62.         Class cls = null;  
  63.         cls = findLoadedClass(name);  
  64.         if (!this.dynaclazns.contains(name) && cls == null)  
  65.             cls = getSystemClassLoader().loadClass(name);  
  66.         if (cls == null)  
  67.             thrownew ClassNotFoundException(name);  
  68.         if (resolve)  
  69.             resolveClass(cls);  
  70.         return cls;  
  71.     }  
  72. }  
  73. /* 
  74.  * 每隔500ms執行一次,不斷載入class 
  75.  */
  76. class Multirun implements Runnable {  
  77.     publicvoid run() {  
  78.         try {  
  79.             while (true) {  
  80.                 // 每次都創建出一個新的類載入器
  81.                 // class需要放在自己package名字的資料夾下
  82.                 String url = System.getProperty("user.dir") + "/lib";// "/lib/yerasel/GetPI.jar";
  83.                 HowswapCL cl = new HowswapCL(url,  
  84.                         new String[] { "yerasel.GetPI" });  
  85.                 Class cls = cl.loadClass("yerasel.GetPI");  
  86.                 Object foo = cls.newInstance();  
  87.                 // 被呼叫函式的引數
  88.                 Method m = foo.getClass().getMethod("Output"new Class[] {});  
  89.                 m.invoke(foo, new Object[] {});  
  90.                 Thread.sleep(500);  
  91.             }  
  92.         } catch (Exception ex) {  
  93.             ex.printStackTrace();  
  94.         }  
  95.     }  
  96. }  
  97. publicclass Test {  
  98.     publicstatic Method initAddMethod() {  
  99.         try {  
  100.             Method add = URLClassLoader.class.getDeclaredMethod("addURL",  
  101.                     new Class[] { URL.class });  
  102.             add.setAccessible(true);  
  103.             return add;  
  104.         } catch (Exception e) {  
  105.             thrownew RuntimeException(e);  
  106.         }  
  107.     }  
  108.     publicstaticvoid main(String[] args) {  
  109.         // 熱部署測試程式碼
  110.         Thread t;  
  111.         t = new Thread(new Multirun());  
  112.         t.start();  
  113.     }  
  114. }  

GetPI.Java內容:

  1. package yerasel;  
  2. import java.io.PrintStream;  
  3. publicclass GetPI  
  4. {  
  5.   publicstaticdouble Darts(int n)  
  6.   {  
  7.     int k = 0;  
  8.     double x = 0.0D;  
  9.     double y = 0.0D;  
  10.     for (int i = 0; i < n; i++)  
  11.     {  
  12.       x = Math.random();  
  13.       y = Math.random();  
  14.       if (x * x + y * y <= 1.0D)  
  15.         k++;  
  16.     }  
  17.     return4 * k / n;  
  18.   }  
  19.   // 本熱部署實驗中,上面的Darts函式沒有用到,請忽略
  20.   publicstaticvoid Output() {  
  21. 相關推薦

    Java Class替換 定義ClassLoader載入.class(java部署實現 )

    本文是java熱替換的實驗,參考了 之前的錯誤是,沒有整合ClassLoader,而是直接使用了 classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();   這個語句只適用於載入.jar

    Java原始碼分析——Class類、ClassLoader類解析(三) 類載入器、實現定義載入

        在這個系列的第一篇章就講解了Class類的獲取以及載入過程,但是並沒有提及具體的載入過程,在java中,載入一個類是通過ClassLoader類來執行的,也就是類載入器完成。java中所有的類,都必須載入進jvm中才能執行,這個載入的意思是

    Java載入器( CLassLoader ) 死磕7: 基於加密的定義網路載入器 本小節目錄

    【正文】Java類載入器(  CLassLoader ) 死磕7:  基於加密的自定義網路載入器 本小節目錄 7.1. 加密傳輸Server端的原始碼 7.2. 加密傳輸Client端的原始碼 7.3. 使用亦或實現簡單加密和解密演算法 7. 網路加密SafeClassLoader的原

    定義ClassLoader,編譯並載入外部java檔案

    /** * java檔案: Test.java,  package: com.chenyf.entity,  所在目錄:F:/today/javadir/src/main/java/com/chenyf/entity/Test.java */ /*** 編譯java檔案,並載入其Cl

    java載入機制和定義載入

    類載入順序 上圖所示的是類載入的順序,按照大的順序可以分為載入、連結、初始化 其中連結又可以分成驗證、準備、解析三個步驟 載入 1.將類的class檔案讀入到記憶體中 載入類檔案的方式有: 1. 本機檔案載入 2.jar包載入 3.網路載入 4.原始檔動態編譯載入

    Java定義載入器與雙親委派模型[轉]

    其實,雙親委派模型並不複雜。自定義類載入器也不難!隨便從網上搜一下就能搜出一大把結果,然後copy一下就能用。但是,如果每次想自定義類載入器就必須搜一遍別人的文章,然後複製,這樣顯然不行。可是自定義類載入器又不經常用,時間久了容易忘記。相信你經常會記不太清loa

    Java 定義 ClassLoader 實現隔離執行不同版本jar包的方式

    1. 應用場景 有時候我們需要在一個 Project 中執行多個不同版本的 jar 包,以應對不同叢集的版本或其它的問題。如果這個時候選擇在同一個專案中實現這樣的功能,那麼通常只能選擇更低版本的 jar 包,因為它們通常是向下相容的,但是這樣也往往會失去新版本

    Java虛擬機器----定義載入器:實現對位元組碼的加密解密

    一、概述         上一篇《Java虛擬機器----類的載入過程》分析了類載入的全過程,本文將以一個示例實現自定義類載入器。         Java 原始檔的編譯結果預設為位元組碼,也就是字尾名為“.class”的檔案,那麼在很多情況下,我們並不希望看到編譯後的位元

    Java定義載入器及JVM帶的類載入器之間的互動關係

    JVM自帶的類載入器: 其關係如下: 其中,類載入器在載入類的時候是使用了所謂的“父委託”機制。其中,除了根類載入器以外,其他的類載入器都有且只有一個父類載入器。 關於父委託機制的說明: 當生成 一個自定義的類載入器例項時,如果沒有指定它的父

    定義ClassLoader

    pla read except object rri mar clas 結果 cnblogs 自定義classloader MapleClassLoader package com.maple; import java.io.*; public class MapleC

    java 註解分析及定義註解

    var AC IE 原始類型 length JD email 文檔 生成 註解概念:   java提供了一種原程序中的元素關聯任何信息和任何元數據的途徑與方法。 註解分類: 運行機制分類:源碼註解,編譯時註解,運行時註解。  來源分類:JDK的註解,第三方註解,自

    定義 Dialog 載入進度,去除定義Dialog的白色背景

    去除自定義Dialog的白色背景: mDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); 這句話就可以了,一定要記得 在show()前加; 下面附上完整程式碼: public c

    java定義註解2】java定義註解結合Spring AOP

          承接上一篇,註解應用於屬性,本篇定義了一個用於方法的註解,結合Spring AOP 實現 切面程式設計。       以下demo演示使用了SpringBoot,與SSM中使用方式大致相同,效果如下: 1、自定義註解(用

    java定義註解1】java定義註解-屬性

            關於自定義註解,以前專案種應用的不多,最近看新專案過程中發現了挺多自定義註解相關內容,使用起來比較巧妙,於是 總結了兩種方式,記錄如下:         第一種:結合反射進行屬性注入,程式碼如下:

    定義View載入進度條首頁面

    1.主頁面佈局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:

    架構探險(三)定義載入

    今天我們來談一談架構探險中自定義的類載入器,一般我們若想實現自定義的類載入器,可以繼承ClassLoader類,然後實現findClass方法即可,詳細介紹可以看以下連結: https://www.cnblogs.com/doit8791/p/5820037.html 本文

    ListView與定義介面卡(顯示java端的資料)

    一、自定義介面卡 1、BaseAdapter:是所有介面卡類的父類,可以對列表項進行最大限度的定製 2、自定義介面卡中的方法 @Override public int getCount() {//從java端獲取到多少條資料 return da

    java-微信分享定義內容功能(總結)

                   java寫微信分享自定義內容功能遇到的一個bug    需求:使用者通過關注公眾號  開啟邀請好友頁面(前提必須先登入)  點選手機右上角豎形

    Java筆記丨25 定義異常

    建立使用者自定義異常時 繼承自Exception類或者某個子Exception類 定義屬性和方法,或者過載父類的方法   重拋異常及異常連結 對於異常,不僅要進行捕獲處理,有時候還需要將此異常進一步傳遞給呼叫者,以便讓呼叫者也能感受到這種異常。這時可以在ca

    Java中Arrays.sort()定義陣列的升序和降序排序

    Java學習中會遇到對陣列進行升序或者降序排序的問題 Java語言提供給我們Array.sort(int [] arr)對陣列進行升序排列 import java.util.Arrays; public class Test1 { public stat