JVM技術細節: HotSpot的內存模型

1、對象無句柄

在早期的JVM版本,例如 Classic VM 實現中,使用了 間接句柄(indirect handle) 來表示對象引用。
雖然使用這種方式使得垃圾收集器在重定位對象(relocating)時非常方便,但卻導致了嚴重的性能瓶頸,因爲每次訪問Java對象的實例變量都需要兩步操作。

HotSpot 推出以後,Java 代碼就不再使用任何句柄。
對象引用使用 直接指針(direct pointer) 方式來實現。 在訪問實例變量時, 其性能和C語言一樣高效。
當然,在內存回收期間,GC重定位(relocated)對象時,則需要查找並更新這個對象的所有引用。

2、用2個機器字表示對象頭

HotSpot VM 使用兩個機器字(machine-word)作爲對象頭(object header),而不是像 Classic VM 那樣使用三個機器字。
由於大部分情況下,Java對象佔用的內存空間平均值都很小,所以將對象頭從3個機器字降到2個機器字的長度,能很明顯地降低內存空間的消耗: 對大部分應用程序來說,節省的堆內存空間在8%左右。

  • 對象頭中, 第一個機器字,用來保存唯一哈希碼,GC狀態信息等等。
  • 第二個機器字用來保存該對象 class 的引用。
  • 數組則特殊一點,其對象頭中有第三個部分(int值),用於保存數組長度。

3、用對象表示反射數據

類(class),方法(method)和其他內部反射數據,都使用堆內存中的對象來表示(雖然這些對象無法通過常規的Java代碼直接訪問)。
這不僅簡化了JVM內部的對象模型,而且還允許垃圾收集器像回收普通Java對象一樣,來回收class。

4、Native線程支持,包括搶佔和多處理

每個線程的活動方法棧(activation stacks), 都使用底層操作系統的棧和線程模型來表示。 Java方法和native方法都使用同樣的棧,從而允許在C語言編寫的JNI方法和Java方法之間進行快速調用。 通過底層操作系統的線程調度機制, 來支持完全搶佔式的Java線程。

使用底層操作系統線程,以及操作系統級的調度, 最主要的優勢在於,能夠透明地利用操作系統對多處理(native OS multiprocessing)的支持。
由於HotSpot VM被設計爲對競態條件不敏感(race condition, 競態條件由搶佔和/或多處理引起), 所以Java線程會自動利用底層操作系統提供的所有調度和處理器分配策略。

原文鏈接

The Java HotSpot Performance Engine Architecture: https://www.oracle.com/technetwork/java/whitepaper-135217.html#memory

發佈了112 篇原創文章 · 獲贊 1704 · 訪問量 530萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章