在 JAVA 虛擬機器(JVM)進程之間共用已經裝載的類,這種概念並不是新的。 例如,Sun 的 CDS 特性將系統類別寫到一個唯讀檔案中,這個檔案在記憶體中映射到 JVM。IBM z/OS® 1.4.2 JVM 中的 Shiraz 特性使用一個主 JVM 填充類緩衝 ,然後從 JVM 可以共用這個類緩衝。
JVM 5.0 的 IBM 實現進一步發展了 這個概念,允許將所有 系統類別和應用程式類儲存在共用記憶體中一個一致的動態類 緩衝中。在支援 JVM 的 IBM 實現的所有平台上都支援這個共用類 特性。這個特 性甚至支援與運行時位元組碼修改進行整合,這將在本文 後面 討論。
共用 類特性是從頭設計的,它是一個可以開啟和關閉的選項,可以減少虛擬記憶體佔用 並改進 JVM 啟動時間。因此,它非常適合多個 JVM 運行相似代碼的環境或者 JVM 常常重新啟動的環境。
除了 JVM 及其類裝載器中的運行時類共用支 持之外,還有一個公用的 Helper API,可以將類共用支援整合到定製的類裝載器 中,本文將 詳細 討論這個問題。
它如何工作
我們先看看共用類 特性如何操作的技術細節。
啟用類共用
啟用類共用的方法是將 - Xshareclasses[:name=<cachename>] 添加到現有的 Java 命令列上。當 JVM 啟動時,它尋找給定名稱的類緩衝(如果沒有提供名稱,那麼選擇一個預設 名稱),並按照需要串連現有的緩衝或建立一個新的緩衝。
使用參數 - Xscmx<size>[k|m|g] 指定緩衝的大小;這個參數只應用於 JVM 建立新緩 存的情況。如果省略這個選項,那麼選擇一個與平台相關的預設值(通常是 16MB )。注意,一些作業系統設定可能會限制可分配的共用記憶體量,例如 Linux 上的 SHMMAX 通常設定為大約 20MB。這些設定的細節可以在適當的使用者指南的 Shared Classes 部分中找到(參見 參考資料 中的連結)。
類緩衝
類緩衝 是一個大小固定的共用記憶體區,它在使用它的 JVM 的生命週期之外仍 然持久地存在。一個系統上可以有任意數量的共用類緩衝,這隻受作業系統設定 的限制;但是一個 JVM 在它的生命週期中只能串連一個緩衝。
JVM 並不擁有緩衝,也沒有主/從 JVM 的概念;實際上,任意數量的 JVM 都 可以並行地讀寫緩衝。在兩種情況下會刪除緩衝:使用 JVM 公用程式顯式地銷毀 它,或者作業系統重新啟動時(緩衝無法在作業系統重新啟動時持久存在)。緩 存的大小無法增長,當它被填滿時,JVM 仍然可以從其中裝載類,但是不能再向 其中添加任何類。有許多用來管理主動式快取的 JVM 公用程式,後面的 “共用類 公用程式” 一節將討論這些程式。
如何對類進行緩衝?
當 JVM 裝載一個類時,它先查看需要的類是否已經在緩衝中存在。如果是這 樣,那麼它從緩衝裝載這個類。否則,它從檔案系統裝載這個類並將其寫到緩衝 中(在 defineClass() 調用中進行這一操作)。因此,不進行共用的 JVM 採用 以下類裝載器尋找次序:
類裝載器緩衝
父類裝載器
檔案系統
與其相反,進行共用的 JVM 採用以下次序:
類裝載器緩衝
父類裝載器
共用快取
檔案系統
使用公用的 Helper API 在緩衝中讀寫類,這個 API 已經整合到了 java.net.URLClassLoader 的 IBM 實現中。因此,任何擴充 java.net.URLClassLoader 的類裝載器都會自動地獲得類共用支援。