程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java技術,IBM風格: 類共享

Java技術,IBM風格: 類共享

編輯:關於JAVA

在 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 的類裝載器都會自動地獲得類共享支持。

類的哪些部分被緩存?

在 JVM 的 IBM 實現中,Java 類分成兩個部分:一個稱為 ROMClass 的只讀 部分,其中包含不可變的所有類數據;一個 RAMClass 部分,其中包含可變的數 據,比如靜態類變量。RAMClass 指向 ROMClass 中的數據,但是這兩部分是完全 分開的,這意味著 ROMClass 可以十分安全地在 JVM 之間共享,甚至在同一個 JVM 中的 RAMClass 之間共享。

在不進行共享的情況下,當 JVM 裝載一個類時,它單獨創建 ROMClass 和 RAMClass 並將它們存儲在自己的本地進程內存中。在進行共享的情況下,如果 JVM 在類緩存中發現了 ROMClass,那麼它只需要在自己的本地內存中創建 RAMClass;RAMClass 引用共享的 ROMClass。

因為大部分類數據存儲在 ROMClass 中,因此可以節省虛擬內存。(“虛擬內 存占用” 一節將詳細討論這個問題。)已經填充的緩存還會顯著改進 JVM 啟動 時間,因為每個緩存的類的一部分定義工作已經完成了,而且會從內存裝載類而 不是從文件系統裝載。填充新緩存導致的啟動時間開銷(在本文後面 討論)並不 顯著,因為每個類只需在定義時重新定位到緩存中。

如果文件系統中的類發生變化,那麼會怎麼樣?

因為緩存是無限期持久存在的,文件系統更新可能會使緩存中的類失效。因此 ,當類裝載器請求一個共享的類時,緩存代碼要負責確保返回的類總是與從文件 系統裝載的類完全一樣。當裝載類時這一檢查會透明地進行,所以用戶可以在共 享類緩存的生命周期內修改和更新任意類,系統總會裝載正確的類。

JVM 探測文件系統更新的方法是,將時間戳值存儲在緩存中並在裝載每個類時 比較緩存的值和實際值。如果它探測到一個 JAR 文件已經更新了,那麼它不知道 哪些類已經更新了,所以緩存中所有從這個 JAR 裝載的類都立即被標為過時的, 不能再從緩存中裝載它們。當從文件系統裝載這個 JAR 中的類並重新添加到緩存 中時,只添加實際修改過的類;那些沒有修改的類實際上沒有過時。

無法從緩存中清除類,但是 JVM 會盡可能高效地利用空間。例如,同樣的類 不會添加兩次,即使它是從許多不同的位置裝載的。所以,如果三個不同的 JVM 分別從 /A.jar、/B.jar 和 /C.jar 裝載同樣的類 C3,類數據仍然只添加一次, 但是有三段元數據描述裝載這個類的三個位置。

共享類實用程序

有許多實用程序可以用來管理活動緩存,它們都是 -Xshareclasses 的子選項 。(輸入 java -Xshareclasses:help 就可以看到 -Xshareclasses 的所有有效 子選項。)

注意,實用程序(除了 expire 之外)實際上不啟動 JVM,它們執行所需的操 作,然後退出,並不運行類。還要注意,每個實用程序都導致 Java 啟動程序輸 出消息 Could not create the Java virtual machine,因為沒有啟動 JVM。這 不是錯誤。

為了演示這些選項的使用方法,我們來看一些示例。首先,用不同的緩存名稱 運行 HelloWorld 類,從而創建兩個緩存,見清單 1:

清單 1. 創建兩個緩存

C:\j9vmwi3223\sdk\jre\bin>java -cp . - Xshareclasses:name=cache1 Hello
Hello
C:\j9vmwi3223\sdk\jre\bin>java -cp . -Xshareclasses:name=cache2 Hello
Hello

運行 listAllCaches 子選項列出系統上的所有緩存並指出是否正在使用它們 ,見清單 2:

清單 2. 列出所有緩存

C:\j9vmwi3223\sdk\jre\bin>java - Xshareclasses:listAllCaches
Shared Cache Last detach time
cache1 Sat Apr 15 18:47:46 2006
cache2 Sat Apr 15 18:51:15 2006
Could not create the Java virtual machine.

運行 printStats 選項輸出指定緩存的統計信息,見清單 3。這裡顯示的字段 的意義請參考用戶指南(參見 參考資料 中的鏈接)。

清單 3. 緩存的統計信息

C:\j9vmwi3223\sdk\jre\bin>java - Xshareclasses:name=cache1,printStats
Current statistics for cache "cache1":
base address = 0x41D10058
end address = 0x42D0FFF8
allocation pointer = 0x41E3B948
cache size = 16777128
free bytes = 15536080
ROMClass bytes = 1226992
Metadata bytes = 14056
Metadata % used = 1%
# ROMClasses = 313
# Classpaths = 2
# URLs = 0
# Tokens = 0
# Stale classes = 0
% Stale classes = 0%
Cache is 7% full
Could not create the Java virtual machine.

對指定的緩存運行 printAllStats 選項列出這個緩存的全部內容以及 printStats 統計信息。會列出緩存中存儲的每個類以及上下文數據,比如類路徑 數據。在清單 4 中,可以看到列出了 JVM 引導類路徑,後面是一些類以及裝載 它們的位置:

清單 4. 列出一個緩存的全部內容

C:\j9vmwi3223\sdk\jre\bin>java -

Xshareclasses:name=cache1,printAllStats
Current statistics for cache "cache1":
1: 0x42D0FAB0 CLASSPATH
C:\j9vmwi3223\sdk\jre\lib\vm.jar
C:\j9vmwi3223 \sdk\jre\lib\core.jar
C:\j9vmwi3223 \sdk\jre\lib\charsets.jar
C:\j9vmwi3223 \sdk\jre\lib\graphics.jar
C:\j9vmwi3223 \sdk\jre\lib\security.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmpkcs.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmorb.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmcfw.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmorbapi.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmjcefw.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmjgssprovider.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmjsseprovider2.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmjaaslm.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmjaasactivelm.jar
C:\j9vmwi3223 \sdk\jre\lib\ibmcertpathprovider.jar
C:\j9vmwi3223 \sdk\jre\lib\server.jar
C:\j9vmwi3223 \sdk\jre\lib\xml.jar
1: 0x42D0FA78 ROMCLASS: java/lang/Object at 0x41D10058.
Index 0 in classpath 0x42D0FAB0
1: 0x42D0FA50 ROMCLASS: java/lang/J9VMInternals at 0x41D106E0.
Index 0 in classpath 0x42D0FAB0
1: 0x42D0FA28 ROMCLASS: java/lang/Class at 0x41D120A8.
Index 0 in classpath 0x42D0FAB0
...

使用 destroy 選項銷毀指定的緩存,見清單 5。使用 destroyAll 銷毀所有 未使用的緩存和用戶有權銷毀的緩存。

清單 5. 銷毀緩存

C:\j9vmwi3223\sdk\jre\bin>java - Xshareclasses:name=cache1,destroy
JVMSHRC010I Shared Cache "cache1" is destroyed
Could not create the Java virtual machine.
C:\j9vmwi3223\sdk\jre\bin>java -Xshareclasses:listAllCaches
Shared Cache Last detach time
cache2 Sat Apr 15 18:51:15 2006
Could not create the Java virtual machine.

expire 選項(見清單 6)是一個可以添加到命令行的清理選項,它的作用是 如果在指定的時間內(分鐘數)沒有 JVM 連接這個緩存,那麼就自動銷毀緩存。 這是惟一一個不會導致 JVM 退出的實用程序。清單 6 尋找一周(大約 10000 分 鐘)內沒有使用過的緩存,並在啟動 VM 之前銷毀它們:

清單 6. 銷毀一周內沒有使用過的緩存

C:\j9vmwi3223\sdk\jre\bin>java -cp . - Xshareclasses:expire=10000,name=cache1 Hello
Hello

詳細選項

詳細選項提供關於類共享正在做什麼的有用反饋。它們都是 -Xshareclasses 的子選項。本節給出一些示例,演示如何使用詳細輸出。

verbose 選項(見清單 7)給出關於 JVM 啟動和關閉的簡明狀態信息:

清單 7. 獲得 JVM 狀態信息

C:\j9vmwi3223\sdk\jre\bin>java -cp . - Xshareclasses:name=cache1,verbose Hello
[-Xshareclasses verbose output enabled]
JVMSHRC158I Successfully created shared class cache "cache1"
JVMSHRC166I Attached to cache "cache1", size=16777176 bytes
Hello
JVMSHRC168I Total shared class bytes read=0. Total bytes stored=1176392

verboseIO 選項將每個類裝載請求的一個狀態行輸出到緩存。為了理解 verboseIO 輸出,應該了解類裝載器的層次結構,這樣才能看出哪些類是由非引 導類裝載器裝載的。在尋找類時,每個類裝載器必須沿著層次結構向上委托請求 ,直到到達引導裝載器。在輸出中,每個類裝載器被賦予一個惟一的 ID,引導裝 載器的 ID 總是 0。

注意,有時候即使類已經被緩存了,verboseIO 仍然顯示從磁盤裝載類並存儲 到緩存中,這是正常的。例如,從應用程序類路徑中的每個 JAR 裝載的第一個類 總是從磁盤裝載並存儲,無論它是否在緩存中存在。

在 清單 8 中,第一部分演示緩存的填充,第二部分演示緩存類的讀取:

verboseHelper 子選項(見 清單 9)是一個高級選項,提供來自 Helper API 的狀態輸出。設計它是為了幫助使用 Helper API 的開發人員了解 Helper API 的操作方式。關於此輸出的更多細節見 JVM 診斷指南(參見 參考資料 中的鏈接 )。

運行時字節碼修改

運行時字節碼修改正在成為將功能加入 Java 類的流行方法。可以使用 JVM Tools Interface(JVMTI)鉤子執行運行時字節碼修改(參見 參考資料 中的鏈 接);另外,類裝載器還可以在定義類之前替換類字節碼。這給類共享帶來了額 外的挑戰,因為一個 JVM 可能緩存經過修改的字節碼,共享同一個緩存的另一個 JVM 不應該裝載它們。

但是,由於 IBM 共享類實現的動態性質,使用不同修改方式的多個 JVM 可以 安全地共享同一個緩存。實際上,如果字節碼修改的開銷很大,那麼對經過修改 的類進行緩存有很大的好處,因為變換只需要執行一次。惟一的要求是字節碼修 改應該是確定性的且可預測的。修改並緩存一個類之後,就不能再修改它。

可以使用 -Xshareclasses 的 modified=<context> 子選項共享經過修 改的字節碼。上下文是一個用戶定義的名稱,它在緩存中創建一個分區,這個 JVM 裝載的所有類都存儲在這個分區中。要使用這個修改版字節碼的所有 JVM 都 應該指定這個上下文名稱,這樣就會從這個緩存分區裝載類。如果使用同一個緩 存的 JVM 沒有指定 modified 子選項,就會按一般方式尋找並存儲類。

潛在的陷阱

如果 JVM 注冊了 JVMTI 代理來修改類字節碼,而且沒有 使用 modified 子 選項,那麼仍然可以安全地管理其他一般 JVM 或使用其他代理的 JVM 之間的類 共享,但是由於要進行額外的檢查,會有一點兒性能開銷。因此,使用 modified 子選項總會提高效率。

注意,只有在 JVMTI 代理存在的情況下,JVM 才能意識到將進行字節碼修改 。因此,如果定制的類裝載器在定義類之前修改類字節碼,但是沒有使用 JVMTI 和 modified 子選項,那麼就假設定義的類是未修改的,其他 JVM 就無法正確地 裝載它們。

關於共享經過修改的字節碼的更詳細信息,請參考 JVM 診斷指南(參見 參考 資料)。

使用 Helper API

IBM 提供了共享類 Helper API,使開發人員能夠將類共享支持集成到定制的 類裝載器中。只有未擴展 java.net.URLClassLoader 的類裝載器才需要 Helper API,因為擴展 java.net.URLClassLoader 的類裝載器會自動繼承類共享支持。

對 Helper API 的全面介紹超出了本文的范圍,但是這裡給出一個一般性概述 。如果想詳細了解 Helper API,在 下載 一節中可以找到完整的 Javadoc,診斷 指南(參考資料)也提供了更多信息。

Helper API:概述

所有 Helper API 類都在 com.ibm.oti.shared 包中,並包含在 jre/lib 目 錄的 vm.jar 中。希望共享類的每個類裝載器都必須從 SharedClassHelperFactory 獲得一個 SharedClassHelper 對象。創建 SharedClassHelper 之後,它屬於請求它的類裝載器,只能存儲這個類裝載器定 義的類。SharedClassHelper 為類裝載器提供一個簡單的 API,可以在 JVM 連接 的類緩存中尋找和存儲類。如果這個類裝載器被垃圾收集,那麼它的 SharedClassHelper 也被垃圾收集。

使用 SharedClassHelperFactory

SharedClassHelperFactory 是一個單實例對象,可以使用靜態方法 com.ibm.oti.shared.Shared.getSharedClassHelperFactory() 獲得它;如果 JVM 中啟用了類共享支持,那麼這個方法返回一個工廠,否則返回 null。

使用 SharedClassHelper

這個工廠可以返回三種不同的 SharedClassHelper,分別供不同類型的類裝載 器使用:

SharedClassURLClasspathHelper:這個 helper 供那些有 URL 類路徑概念的 類裝載器使用。使用 URL 類路徑數組在緩存中存儲和尋找類。必須可以通過類路 徑中的 URL 資源訪問文件系統上要緩存的類。這個 helper 還對在它的生命周期 內如何修改類路徑有一些限制。

SharedClassURLHelper:這個 helper 供那些沒有類路徑概念,可以從任意 URL 裝載類的類裝載器使用。必須可以通過 URL 資源訪問文件系統上要緩存的類 。

SharedClassTokenHelper:這個 helper 實際上將共享類緩存轉換為一個簡單 的哈西表 —— 類按照一個對於緩存無意義的字符串鍵標志 進行存儲。這是惟一 一種不提供動態更新功能的 helper,因為存儲的類沒有相關聯的文件系統上下文 。

每個 SharedClassHelper 都有兩個基本方法,但是在 helper 類型之間方法 的參數有差異:

在類裝載器向它的父類裝載器請求類(如果存在的話)之後,應該調用 byte [] findSharedClass(String classname...)。如果 findSharedClass() 沒有返 回 null,那麼類裝載器應該在返回的字節數組上調用 defineClass()。注意,這 個函數為 defineClass() 返回一個特殊的 cookie,而不是實際的類字節,所以 不能修改字節。

在定義一個類之後,應該立即調用 boolean storeSharedClass(Class clazz...)。如果成功地存儲了這個類,那麼這個方法返回 true,否則返回 false。

其他考慮因素

在應用程序中部署類共享時,需要考慮到安全性和緩存調整等因素。這裡簡短 地討論這些考慮因素。

安全性

在默認情況下,以用戶級安全性創建類緩存,所以只有創建這個緩存的用戶才 能訪問它。因此,每個用戶的默認緩存名稱是不同的,從而避免了沖突。在 UNIX 上,有一個指定 groupAccess 的子選項,它允許創建這個緩存的用戶的主組中的 所有用戶訪問這個緩存。但是,不管使用什麼訪問級別,只有創建緩存的用戶或 根用戶能夠銷毀緩存。

除此之外,如果安裝了 SecurityManager,那麼類裝載器只能在被顯式地授予 正確權限的情況下共享類。關於設置這些權限的更多細節,請參考用戶指南(參 見 參考資料)。

垃圾收集和即時編譯

啟用類共享並不影響類的垃圾收集(GC)。仍然按照非共享情況下的方式對類 和類裝載器進行垃圾收集。另外,在使用類共享時,對 GC 模式或配置沒有限制 。

不能將即時(JIT)編譯的代碼存儲在類緩存中,所以在啟用類共享時 JIT 的 行為沒有變化。

緩存大小限制

當前緩存大小的理論最大值是 2GB。緩存大小受到以下因素的限制:

可用磁盤空間(只適用於 Microsoft Windows)。 在 javasharedresources 目錄中創建一個內存映射文件來存儲類數據。這個目錄在用戶的 %APPDATA% 目錄 中創建。每當重新啟動 Windows 時,刪除共享緩存文件。

可用系統內存(只適用於 UNIX)。 在 UNIX 上,緩存放在共享內存中,JVM 將一個配置文件寫到 /tmp/javasharedresouces,從而讓所有 JVM 能夠根據名稱 找到共享內存區域。

可用虛擬地址空間。 因為進程的虛擬地址空間在共享類緩存和 Java 堆之間 分享,所以增加 Java 堆的大小會減小可以創建的共享類緩存。

一個示例

為了實際演示類共享的好處,本節提供一個簡單的圖形演示程序。這個程序的 源代碼和二進制代碼可以從 下載 一節獲得。

這個演示程序搜索 jre\lib 目錄並打開每個 JAR,在找到的每個類上調用 class.forName()。這會將大約 12,000 個類裝載到 JVM 中。演示程序報告 JVM 花了多長時間裝載這些類。顯然,這是個有點兒不自然的示例,因為這個測試只 進行類裝載,但是它確實展現了類共享的好處。我們來運行這個應用程序並看看 結果。

類裝載的性能

從 下載 一節下載 shcdemo.jar。

使用清單 10 中的命令,在不啟用類共享的情況下兩次運行這個測試,從而對 系統磁盤緩存進行 “預熱”:

清單 10. 對磁盤緩存進行預熱

C:\j9vmwi3223\sdk\jre\bin>java -cp C:\shcdemo.jar ClassLoadStress

當出現圖 1 所示的窗口時,按下按鈕。應用程序將裝載類。

圖 1. 按下按鈕

裝載類之後,應用程序報告它裝載了多少個類以及花費的時間,見圖 2:

圖 2. 結果

您會注意到,應用程序每次運行時都可能會快一點兒;這是由於操作系統優化 造成的。

現在在啟用類共享的情況下運行這個演示程序,見 清單 11。會創建一個新的 緩存,所以這次運行顯示了填充新緩存所花費的時間。應該將緩存的大小指定為 大約 50MB,從而確保能夠存儲所有的類。清單 11 給出命令行和一些輸出示例。

如圖 3 所示,這次運行花費的時間應該比前幾次略微長一點兒,因為演示程 序要填充共享類緩存。還可以使用 printStats(見清單 12)來查看共享類緩存 中存儲的類的數量:

圖 3. 冷緩存的結果

清單 12. 查看緩存類的數量

C:\j9vmwi3223\sdk\jre\bin>java - Xshareclasses:name=demo,printStats
Current statistics for cache "demo":
base address = 0x41D10058
end address = 0x44F0FFF8
allocation pointer = 0x44884030
cache size = 52428712
free bytes = 6373120
ROMClass bytes = 45563864
Metadata bytes = 491728
Metadata % used = 1%
# ROMClasses = 12212
# Classpaths = 3
# URLs = 0
# Tokens = 0
# Stale classes = 0
% Stale classes = 0%
Cache is 87% full
Could not create the Java virtual machine.

現在,用同樣的 Java 命令行再次啟動這個演示程序。這一次,它應該會從共 享類緩存中讀取類,見 清單 13。

可以清楚地看到類裝載時間方面的顯著改進。同樣,由於操作系統優化,每次 運行這個演示程序時都應該會看到性能略微提高。運行這個測試所用的是一個單 處理器的 1.6 GHz x86 兼容筆記本,運行的操作系統是 Windows XP:

圖 4. 熱緩存的結果

還可以測試許多不同的情況。例如,可以使用 javaw 命令並啟動多個演示程 序,讓它們一起裝載所有的類,從而觀察並行性能。

在真實的場景中,通過使用類共享獲得的 JVM 啟動時間收益取決於應用程序 裝載的類數量:HelloWorld 這樣的簡單程序體現不出很大的收益,但是大型 Web 服務器得到的收益肯定很大。無論如何,這個示例說明對類共享進行實驗是非常 容易的,所以您可以輕松地測試受益的程度。

虛擬內存占用

在多個 JVM 中運行示例程序時,很容易看出虛擬內存的節省。

下面兩張 Task Manager 屏幕圖是使用與前例相同的機器獲得的。在圖 5 中 ,運行了演示程序的 5 個實例,沒有啟用類共享。在圖 6 中,使用與前面一樣 的命令行運行了 5 個實例,啟用了類共享:

圖 5. 沒有啟用類共享的 5 個演示程序

圖 6. 啟用了類共享的 5 個演示程序

可以清楚地看到,在啟用類共享的情況下提交開銷相當低。Windows 將 VM 大 小加在一起計算出提交開銷。因為共享的緩存類數據的總量大約是 45MB,可以看 到每個 JVM 的內存使用量大約是 VM 大小加上緩存的類數據量。

這兩個示例開始之前的提交開銷是大約 295MB。這意味著第一個示例使用 422MB,第二個示例使用 244 MB,節省了 178MB。

結束語

Java 5.0 平台的 IBM 實現中新的共享類特性為減少虛擬內存占用和改進 JVM 啟動時間提供了一個簡單且靈活的方法。在本文中,您看到了如何啟用這個特性 、如何使用緩存實用程序以及如何對收益進行度量。

本系列的最後一篇文章將介紹 Java 平台的 IBM 實現中一些新的調試、監視 和分析工具。還將講解如何使用它們快速地分析和調試 Java 應用程序。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved