麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

在運行時刻更新功能模塊

2019-11-18 13:26:44
字體:
來源:轉載
供稿:網友

  本文介紹了一個利用類庫加載器ClassLoader 實現在運行時刻更新部分功能模塊的java程序,并將其與C/C++中實現同樣功能的動態鏈接庫方案進行了簡單比較。
  介紹
  在嵌入式系統的設計中,經常涉及到在運行時刻更新部分功能模塊的設計。例如一個用于數據采集與處理的設備,包括數據采集,數據發送,命令接收等功能模塊,有可能被要求在繼續進行數據采集的同時采用新的數據格式向一個新的數據處理系統發送數據。在這種情況下,就必須在運行時刻動態的更新數據發送的功能模塊。
  
  在C/C++中,這樣的功能可以很輕易的利用動態鏈接庫來實現。Win32 API函數LoadLibrary和FreeLibrary提供了在運行時刻加載新的功能模塊和釋放內存空間的功能。需要被更新的功能模塊被封裝在動態連接庫里,主程序利用LoadLibrary 函數裝載該動態鏈接庫,然后調用其中的功能模塊。需要更新某功能模塊的時候,首先終止運行該功能模塊,利用FreeLibrary 函數卸載現有的動態鏈接庫,通過網絡或者是其他通訊端口將新的動態鏈接庫文件發送到指定目錄下,然后利用再次利用LoadLibrary 函數裝載新的動態鏈接庫并調用其中的新功能模塊。(假如需要進一步了解動態鏈接庫程序設計的內容,請參閱參考文獻1中的相關部分。)
  
  在Java中,有一個被稱為類庫加載器的抽象類ClassLoader 能夠用來實現類似于LoadLibrary的功能。本文下面的部分著重介紹ClassLoader的一般結構以及利用ClassLoader實現在運行時刻更新部分功能模塊的方法。
  
  類庫加載器
  類庫加載器ClassLoader 是一個負責加載類庫的抽象類。它接受一個類庫的名稱并試圖定位和生成包含有改類庫定義的數據。通常的實現方法是將該類庫的名稱轉化成一個文件名,然后從文件系統中找到該文件并讀取其中的內容。(關于類庫加載器的定義,請參閱參考文獻2。)
  
  所有的Java虛擬機都包括一個內置的類庫加載器。這個內置的類庫加載器被稱為主類庫加載器。主類庫加載器的非凡之處是它只能夠加載在設計時刻已知的類,因此虛擬機假定由主類庫加載器所加載的類都是可信任的,可以不經過安全認證而直接運行。當應用程序需要加載在設計時刻未知的類庫時,就必須使用用戶自定義的類庫加載器。
  
  一個用戶自定義的類庫加載器是抽象類java.lang.ClassLoader 的派生類,其中唯一必須實現的抽象方法是loadClass()。通常來說,loadClass()方法需要實現如下操作:
  
  確認類庫名稱
  檢查請求加載的類庫是否已經被加載
  檢查請求加載的類庫是否是系統類庫
  嘗試從類庫加載器的存儲區獲取所清求的類庫
  在虛擬機中定義所請求的類庫
  解析所請求的類庫
  返回所請求的類庫
  
  一個用戶自定義類庫加載器幾乎可以從任何存儲設備上加載類庫。裝載本地硬盤上的類庫當然不在話下,通過超級連接裝載網絡上的類庫也很輕易。由于類庫加載器的存在,Java虛擬機并不需要事先知道關于將要運行的類庫的任何細節。由于類庫加載器的功能是如此的強大,出于安全考慮某些Java類庫如applets 等不答應啟用自定義的類庫加載器。
  
  參考文獻3 給出了關于用戶自定義類庫的更具體描述,同時提供了一個示例程序SimpleClassLoader。在本文下面的例子中,使用該文獻中的SimpleClassLoader作為用戶自定義類庫加載器。
  
  在運行時刻更新功能模塊
  在動態鏈接庫技術中,LoadLibrary函數負責加載功能模塊,FreeLibrary函數負責卸載功能模塊。新的功能模塊與舊的功能模塊同名,新的動態鏈接庫文件也與舊的動態鏈接庫文件同名。當需要更新某個功能模塊的時候,使用新的動態鏈接庫文件替換舊的動態鏈接庫文件,被舊的功能模塊所占用的內存空間也同時被釋放。
  
  但是Java并不提供一個類似于類庫卸載器(ClassUnloader) 的功能,能夠把已經裝載的功能模塊從內存里面清除掉。目前的虛擬機,大都使用了及時編譯(JIT) 技術,也就是說一個功能模塊只有在它第一次被使用的時候才被編譯。經過編譯的可執行代碼被放到內存里面,用一個HashTable 做索引,其要害字為與之相對應的類庫名。虛擬機需要用到某個功能模塊的時候,它先到這個HashTable 里面查找相應的要害字。假如該功能模塊已經存在,虛擬機直接從內存里調用經過編譯的可執行代碼,反之則調用類庫加載器裝載新的功能模塊并進行編譯。由于沒有模塊卸載功能,在運行時刻已經被裝載的功能模塊是一直存在的。當某功能模塊實際上已經被更新(即.class文件被替換為同名的新文件)并需要被重新加載的時候,虛擬機并不會試圖裝載新的功能模塊而直接調用舊的功能模塊。假如試圖利用用戶自定義的類庫加載器強行裝載新的功能模塊,則會因為新的功能模塊與舊的功能模塊同名而導致虛擬機拋出鏈接錯誤: Linkage Error: duplicate class definition。
  
  腦子快的朋友也許已經想出了以下的方法:
   SimpleClassLoader scl = new SimpleClassLoader();
   Object o;
   Class c;
  
   c = scl.loadClass("SomeNewClass");
   o = c.newInstance();
   ((SomeNewClass) o).SomeClassMethod(SomeParam);
  
  
  
  
  但是,這樣的方法實際上是不能夠實現的。首先,SomeNewClass在程序設計的時候尚未存在,這樣的程序是無法通過編譯的。其次,在運行時刻只有用戶自定義的類庫加載器SimpleClassLoader能夠獲取有關SomeNewClass 的定義,虛擬機的主類庫加載器是無法創建一個SomeNewClass對象的,因此以上程序的最后一行也會出錯。
  
  參考文獻3 指出有兩個方法可以解決這個問題。一是被裝載的模塊是虛擬機的主類庫加載器已經加載的某個類庫的派生類庫(subclass),一是被加載的模塊實現某個已經被系統虛擬機的主類庫加載器加載的接口(interface)。 在瀏覽器中通常都使用了第一種方法,譬如說所有的applet都是java.applet.Applet的派生類庫,因此在所有的applet源代碼中都有類似于public class MyClass extends Applet 的聲明。在這里我們采用參考文獻3 中介紹的第二種方法,也就是被加載的新模塊實現某個預先設計好的接口。
  
  聲明接口UpdatableModule如下:
   public interface UpdatableModule
   {
   void start(String RunTimeParam)
   }
  
  
  
  由于這個接口在設計時刻已經存在,它可以被虛擬機的主類庫加載器和將要被加載的新功能模塊所調用。新功能模塊所需要做的,只是實現這個接口中的方法,例如:
   public class NewModule_1 implements UpdatableModule
   {
   void start(String RunTimeParam)
   {
   System.out.   }
   }
   public class NewModule_2 implements UpdatableModule
   {
   void start(String RunTimeParam)
   {
   System.out.println("This is new module 2.");
   }
   }
  
  
  
  在運行時刻,主程序需要從外部獲得新的功能模塊名,利用用戶自定義的類庫加載器加載新的功能模塊,生成一個新的功能模塊對象,然后通過事先定義好的接口調用新的功能模塊中的方法。例如:
  public class Test
   {
   public static void main(String[] args)
   {
   SimpleClassLoader scl = new SimpleClassLoader();
   String RunTimeModule;
   Object o;
   Class c;
   RunTimeModule = args[0];
   c = scl.loadClass(RunTimeModule);
   o = c.newInstance();
   ((UpdatableModule) o).start("No parameter needed.");
   }
   }
  
  
  
  
  示范程序
  下面我們介紹一個簡單的數據采集與處理程序。該程序采集當前的系統時間并按照一定的格式輸出到標準輸出設備,其中的數據處理模塊(即數據輸出模塊)可以在運行時刻被更新。該程序包括如下功能模塊:
  DataBuffer---------數據緩沖區
  DataCollector------數據采集模塊
  DataProcessor------數據處理模塊接口
  PrintData_1--------數據輸出模塊,實現數據處理模塊DataProcessor的接口
  PrintData_2--------數據輸出模塊,實現數據處理模塊DataProcessor的接口
  TestGUI------------測試圖形界面
  數據緩沖區DataBuffer存放數據采集模塊DataCollector 所采集的數據,它提供了更新數據和查詢數據的方法。
   public class DataBuffer
   {
   private String data;
  
   // 更新數據的方法
  
   public synchronized void UpdateData(String s)
   {
   data = s;
   notifyAll();
   }
  
   // 查詢數據的方法
  
   public String GetData()
   {
   return data;
   }
   }
  
  
  
  
  數據采集模塊DataCollector是一個線程,它每隔5秒鐘采集一次系統時間并更新數據緩沖區DataBuffer。
   import java.util.Calendar;
  
   public class DataCollector extends thread
   {
   private DataBuffer DB;
  
   // 構造函數
  
   public D

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 欧美激情猛片xxxⅹ大3 | 免费激情视频网站 | av日韩一区二区 | 欧美日韩亚洲另类 | 国产精品久久久久久久hd | 国产午夜精品久久久 | 中文字幕在线播放视频 | 成人免费观看在线 | 九九热精品在线播放 | 国产乱淫a∨片免费观看 | 欧美国产91 | 91久久免费 | 99精品国产成人一区二区 | 亚洲一区二区在线视频 | 一本在线高清码电影 | 久久影院午夜 | 国产日韩三区 | 免费a级黄色片 | 欧美性猛交xxxxx按摩国内 | 久久综合福利 | 国产成视频在线观看 | 免费在线观看成人网 | 免费毛片电影 | 精品成人网 | 国产毛片网站 | 日韩一级免费 | 久久国产精品成人免费网站 | 黄色影院av | 情侣啪啪网站 | 中国黄色一级生活片 | 日本一道aⅴ不卡免费播放 久久久久久久高清 | 一区二区三区在线观看免费视频 | 成年免费大片黄在线观看岛国 | 青青青在线免费 | av在线等 | 久久精品国产99久久久古代 | 久久久国产精品网站 | 中文字幕四区 | 依人在线视频 | 91黄瓜视频 | 国产一区二区国产 |