熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

實現JAVA的動態類載入機制

2013-11-23 19:19:36  來源: Java核心技術 

   作 為 充 分 利 用Java 的 動 態 類 載 入 機 制 的 最 好 例 子 帶 有Java 擴 展 的Web 浏 覽 器 根 據 請 求 從 網 絡 或 本 地 文 件 系 統 中 動 態 加 載Java applet( 遵 循 一 定 規 則 的Java 小 應 用 程 序 類) 然 後 在 本 地 系 統 中 執 行 它 大 大 增 強 了 主 頁 的 功 能
  
   其 實Java 本 身 就 是 一 種 極 具 動 態 性 的 語 言 類 似Windows 的 動 態 鏈 接 庫(DLL)Java 應 用 程 序 總 是 被 編 譯 成 若 干 個 單 獨 的class 文 件 程 序 執 行 時 根 據 需 要 由Java 虛 擬 機 動 態 載 入 相 應 的 類 這 種 機 制 使 編 寫 動 態 的 分 布 式 應 用 程 序 成 為 可 能 我 們 可 以 在 客 戶 端 編 寫 自 己 的 類 載 入 器 而 真 正 執 行 的 程 序 卻 存 放 在 本 地 局 域 網 或 世 界 另 一 端 的 主 機 上 下 面 將 介 紹 如 何 在 自 己 的 應 用 程 序 中 實 現Java 的 動 態 類 載 入 機 制
  
  與 動 態 類 載 入 有 關 的 系 統 類
   為 支 持 動 態 類 載 入 機 制 在 系 統 類 組javalang 中 提 供 了 兩 個 類Class 類 和ClassLoader 類
  
   類javalangClass 在Java 虛 擬 機 中 每 一 個 類 或 接 口 都 是 由Class 類 來 操 縱 的 它 不 能 被 顯 式 的 實 例 化 必 須 用 其 他 方 法 來 獲 取Class 類 的 對 象 動 態 類 載 入 機 制 的 關 鍵 一 步 在 於 如 何 獲 得 指 定 類 的Class 類 型 的 對 象 相 關 方 法 主 要 有
  
   public static Class forName(String className)
  
   這 是 一 個 靜 態 方 法 它 獲 取 指 定 名 字 的 類 的Class 類 型 對 象 類 名 可 以 是 象sunappletApplet 這 樣 的 字 符 串 但 不 能 帶 有 路 徑 或 網 絡 地 址 等 信 息 這 是 從 本 地 系 統 中 動 態 載 入 類 的 最 方 便 的 辦 法
  
   public Object newInstance()
  
   這 是 最 重 要 的 一 個 方 法 它 建 立 由Class 類 型 對 象 描 述 的 指 定 類 的 實 例
  
   下 面 是 一 個 用forName() 和newInstance() 方 法 實 現 動 態 類 載 入 的 代 碼share 類 包 含 一 個 接 口 詳 細 內 容 將 在 第 三 部 分 中 解 釋
  
  try{
  //根據類名建立Class類型的對象
  Class cc =ClassforName(類名))
  //建立被載入類類的實例並強制類型轉換
  值賦給share類型的變量
  share oo=((share)cc)newInstance();
  //調用該類的方法進行工作
  }
  catch (Exception ex){
  //如果發生例外則進行相應處理
  };
  
   類javalangClassLoader 這 是 一 個 抽 象 類 如 果 打 算 運 用 它 必 須 繼 承 它 並 重 寫 它 的loadClass() 方 法 其 主 要 方 法 有
  
   protected ClassLoader();
  
   這 是 一 個 建 構 元 可 以 用 它 建 立 一 個ClassLoader 類 的 實 例 注 意 繼 承 這 個 類 的 類 必 須 重 寫 這 個 方 法 而 不 能 使 用 缺 省 的 建 構 元
  
   protected abstract Class loadClass(String name boolean resolve)
  
   載 入 指 定 的 類 數 據 建 立Class 類 型 的 對 象 並 根 據 需 要 解 析 它 這 是 一 個 抽 象 方 法 大 家 必 須 在 自 己 的 子 類 中 重 寫 這 個 方 法 重 寫 的 規 則 可 以 參 考 第 三 部 分 的 例 子
  
   protected final Class defineClass(byte data[] int offset int length)
  
   將 字 節 數 組 中 的 數 據 定 義 為Class 類 型 的 對 象 字 節 數 組 的 格 式 由 虛 擬 機 規 定
  
   protected final Class findSystemClass(String name)
  
   根 據 指 定 的 類 名 載 入 類 它 會 自 動 在 當 前 目 錄 和 環 境 變 量CLASSPATH 指 定 的 路 徑 中 尋 找 如 果 找 不 到 則 會 拋 出ClassNotFoundException 例 外
  
   protected final void resolveClass(Class c)
  
   通 過 載 入 與 指 定 的 類 相 關 的 所 有 類 來 解 析 這 個 類 這 必 須 在 類 被 使 用 之 前 完 成
  
  擴 充ClasslLader 類 以 實 現 動 態 類 載 入
   理 解 動 態 類 載 入 機 制 的 最 好 辦 法 是 通 過 例 子 下 面 這 個 完 整 的 例 子 由 四 個 類 組 成 分 別 解 釋 如 下
  
   MyClassLoader 類 是ClassLoader 類 的 子 類 它 重 寫 了loadClass 方 法 實 現 了 將 網 絡 上 用URL 地 址 指 定 的 類 動 態 載 入 取 得 它 的Class 類 型 對 象 的 功 能 讀 者 可 根 據 自 己 載 入 類 的 具 體 方 式 改 寫 下 面 的 代 碼
  
  import javaio*;
  import javautil*;
  import *;
  
  public class MyClassLoader extends ClassLoader {
  //定義哈希表(Hashtable)類型的變量
  用於保存被載入的類數據
  Hashtable loadedClasses;
  
  public MyClassLoader() {
  loadedClasses = new Hashtable();
  }
  
  public synchronized Class loadClass(String className
  boolean resolve) throws ClassNotFoundException {
  Class newClass;
  byte[] classData;
  
  //檢查要載入的類數據是否已經被保存在哈希表中
  newClass = (Class) loadedClassesget(className);
  //如果類數據已經存在且resolve值為true則解析它
  if (newClass != null){
  if (resolve)
  resolveClass(newClass);
  return newClass;
  }
  
   /* 首 先 試 圖 從 本 地 系 統 類 組 中 載 入 指 定 類 這 是 必 須 的 因 為 虛 擬 機 將 這 個 類 載 入 後 在 解 析 和 執 行 它 時 所 用 到 的 任 何 其 他 類 如javalangSystem 類 等 均 不 再 使 用 虛 擬 機 的 類 載 入 器 而 是 調 用 我 們 自 制 的 類 載 入 器 來 加 載*/
  
  try {
  newClass = findSystemClass(className);
  return newClass;
  } catch (ClassNotFoundException e) {
  Systemoutprintln(className+ is not a system class!);
  }
  
  //如果不是系統類
  則試圖從網絡中指定的URL地址載入類
  try {
  //用自定義方法載入類數據
  存放於字節數組classData中
  classData = getClassData(className);
  //由字節數組所包含的數據建立一個class類型的對象
  newClass = defineClass(classData classDatalength);
  if (newClass == null)
  throw new ClassNotFoundException(className);
  } catch (Exception e) {
  throw new ClassNotFoundException(className);
  }
  
  //如果類被正確載入
  則將類數據保存在哈希表中以備再次使用
  loadedClassesput(className newClass);
  //如果resolve值為true則解析類數據
  if (resolve){
  resolveClass(newClass);
  }
  return newClass;
  }
  //這個方法從網絡中載入類數據
  protected byte[] getClassData(String className)
  throws IOException {
  byte[] data;
  int length;
  try {
  //從網絡中采用URL類的方法
  載入指定URL地址的類的數據
  URL url = new URL(classNameendsWith(class) ?
  className : className + class);
  URLConnection connection = urlopenConnection();
  InputStream inputStream = connectiongetInputStream();
  length = connectiongetContentLength();
  
  data = new byte[length];
  inputStreamread(data);
  inputStreamclose();
  return data;
  } catch(Exception e) {
  throw new IOException(className);
  }
  }
  }
  
   由 於Java 是 強 類 型 檢 查 語 言 通 過 網 絡 載 入 後 的 類 被 實 例 化 後 只 是 一 個Object 類 型 的 對 象 虛 擬 機 並 不 知 道 它 包 含 那 些 方 法 應 從 哪 個 方 法 開 始 執 行 因 此 可 以 被 動 態 載 入 的 類 必 須 繼 承 某 一 個 抽 象 類 或 實 現 某 一 個 接 口 因 為 父 類 只 能 有 一 個 所 以 通 常 用 實 現 特 定 接 口 的 辦 法 下 面 的 代 碼 定 義 了 一 個 接 口 類share 和 它 的 方 法start()
  
  public interface share {
  public void start(String[] option);
  }
  
   TestClassLoader 類 通 過 使 用MyClassLoader 類 的loadClass() 方 法 將 指 定URL 地 址 的 類 載 入 並 在 本 地 系 統 執 行 它 實 現 了 類 的 動 態 載 入 注 意 在 執 行 被 載 入 類 的 方 法 前 一 定 要 將 它 進 行 強 制 數 據 類 型 轉 換
  
  public class TestClassLoader {
  public static void main(String[] args){
  MyClassLoader ll = new MyClassLoader(); <
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26668.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.