從 Java 代碼到 Java 堆 理解和優化您的應用程序的內存使用

從 Java 代碼到 Java 堆

理解和優化您的應用程序的內存使用

https://www.ibm.com/developerworks/cn/java/j-codetoheap/

 

優化應用程序代碼的內存使用並不是一個新主題,但是人們通常並沒有很好地理解這個主題。本文將簡要介紹 Java 進程的內存使用,隨後深入探討您編寫的 Java 代碼的內存使用。最後,本文將展示提高代碼內存效率的方法,特別強調了 HashMapArrayList 等 Java 集合的使用。

背景信息:Java 進程的內存使用

參考知識

如需進一步瞭解 Java 應用程序的進程內存使用,請參閱 Andrew Hall 撰寫的 developerWorks 文章 “內存詳解”。這篇文章介紹了 內存詳解 以及 AIX® 提供的佈局和用戶空間,以及 Java 堆和本機堆之間的交互。

通過在命令行中執行 java 或者啓動某種基於 Java 的中間件來運行 Java 應用程序時,Java 運行時會創建一個操作系統進程,就像您運行基於 C 的程序時那樣。實際上,大多數 JVM 都是用 C 或者 C++ 語言編寫的。作爲操作系統進程,Java 運行時面臨着與其他進程完全相同的內存限制:架構提供的尋址能力以及操作系統提供的用戶空間。

架構提供的內存尋址能力依賴於處理器的位數,舉例來說,32 位或者 64 位,對於大型機來說,還有 31 位。進程能夠處理的位數決定了處理器能尋址的內存範圍:32 位提供了 2^32 的可尋址範圍,也就是 4,294,967,296 位,或者說 4GB。而 64 位處理器的可尋址範圍明顯增大:2^64,也就是 18,446,744,073,709,551,616,或者說 16 exabyte(百億億字節)。

處理器架構提供的部分可尋址範圍由 OS 本身佔用,提供給操作系統內核以及 C 運行時(對於使用 C 或者 C++ 編寫的 JVM 而言)。OS 和 C 運行時佔用的內存數量取決於所用的 OS,但通常數量較大:Windows 默認佔用的內存是 2GB。剩餘的可尋址空間(用術語來表示就是用戶空間 )就是可供運行的實際進程使用的內存。

對於 Java 應用程序,用戶空間是 Java 進程佔用的內存,實際上包含兩個池:Java 堆和本機 (非 Java)堆。Java 堆的大小由 JVM 的 Java 堆設置控制:-Xms-Xmx 分別設置最小和最大 Java 堆。在按照最大的大小設置分配了 Java 堆之後,剩下的用戶空間就是本機堆。圖 1 展示了一個 32 位 Java 進程的內存佈局:


圖 1. 一個 32 位 Java 進程的內存佈局示例
一個 32 位 Java 進程的內存佈局示例視圖

圖 1 中,可尋址範圍總共有 4GB,OS 和 C 運行時大約佔用了其中的 1GB,Java 堆佔用了將近 2GB,本機堆佔用了其他部分。請注意,JVM 本身也要佔用內存,就像 OS 內核和 C 運行時一樣,而 JVM 佔用的內存是本機堆的子集。

Java 對象詳解

在您的 Java 代碼使用 new 操作符創建一個 Java 對象的實例時,實際上分配的數據要比您想的多得多。例如,一個 int 值與一個 Integer 對象(能包含 int 值的最小對象)的大小比率是 1:4,這個比率可能會讓您感到吃驚。額外的開銷源於 JVM 用於描述 Java 對象的元數據,在本例中也就是 Integer

根據 JVM 的版本和供應的不同,對象元數據的數量也各有不同,但其中通常包括:

  • :一個指向類信息的指針,描述了對象類型。舉例來說,對於 java.lang.Integer 對象,這是 java.lang.Integer 類的一個指針。
  • 標記 :一組標記,描述了對象的狀態,包括對象的散列碼(如果有),以及對象的形狀 (也就是說,對象是否是數組)。
  • :對象的同步信息,也就是說,對象目前是否正在同步。

對象元數據後緊跟着對象數據本身,包括對象實例中存儲的字段。對於 java.lang.Integer 對象,這就是一個 int

如果您正在運行一個 32 位 JVM,那麼在創建 java.lang.Integer 對象實例時,對象的佈局可能如圖 2 所示:


圖 2. 一個 32 位 Java 進程的 java.lang.Integer 對象的佈局示例
一個 32 位 Java 進程的 java.lang.Integer 對象的佈局示例

圖 2 所示,有 128 位的數據被佔用,其中用於存儲 int 值的爲 32 位,而對象元數據佔用了其餘的 96 位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章