1. 程式人生 > >jvm oop-klass物件模型

jvm oop-klass物件模型

jvm物件模型可以從hotspot7的原始碼中學習.本文內容都是以jdk7對應的hotspot虛擬機器為基礎進行分析的.

一.oop-klass的層級關係
首先,從oopsHierarchy.hpp的原始碼.看看jvm物件模型的層次結構.
引用Hotspot實戰裡面的一張圖,oop各模組的組成:
這裡寫圖片描述

oop層級部分:
oop層級關係

klass層級部分:
klass層級部分

二.oop層級部分:
看完了jvm整個模型的構成,我們先來看看oop部分.
參考hotspot原始碼中的oop.hpp部分.

oop.hpp翻譯:
1.oopDesc是物件類的頂層基類。
2.Desc類描述了Java物件的格式,以便可以從C ++訪問這些欄位。
3.oopDesc是抽象的。(完整的類層次結構見oopHierarchy).
4.oop類不允許虛擬功能.

我們可以將oop的部分理解成java部分的物件,然後klass是給jvm使用的內部物件.
下面是oop各子類的作用和繼承關係.
oop繼承關係
不同型別有不同的用處,比如;建立一個Java物件例項的時候,jvm會建立一個instanceOopDesc物件在java層面來表示這個Java物件。如果是建立一個方法的時候,JVM會建立一個methodOopDesc物件來表示這個方法。

oop物件頭
所有的子類oop都是繼承的oopDesc,我們知道jvm中的物件包含了三部分:物件頭,例項資料,對其填充.其中_mark,_metadata一起合成為了物件頭,裡面包含了鎖狀態標誌、執行緒持有的鎖等標誌
_metadata包含了兩個指標,指向klass,klass包含了例項物件的元資料.

三.klass層級部分.
我們知道Hotspot的底層實現使用C++實現的,C++也是一門面向物件的語言,因此,當講到jvm的物件模型的實現時候,可能會想到,只要java物件底層對應一個C++物件,問題就解決了.在查看了一下參考資料發現,設計者為了避免每個物件中都有一個C++VTBL指標,採用了將物件模型一分為二的做法:oop-klass模型.看到這裡可能會有點懵逼這個C++VTBL指標是幹嘛的.這個不是本文重點,先略過.首先,我們這麼理解,一個C++物件要實現兩部分功能:
1.語言層面的物件;
2.包含虛擬函式;(先簡單的理解為實現多型要用的).

然後我們看klass原始碼中的描述
klass.hpp翻譯:
Klass是klassoop的一部分,它提供了:
1.語言層面的java類物件(方法字典等)
2.為該物件提供了虛擬機器的排程行為
這兩個功能完成了一個C++類的功能。頂層的Klass實現第一點,而所有子類提供額外的虛擬功能實現了第二點.
因此.java的oop-klass物件模型中,klass和其子類就實現了C++物件中的這兩個功能.
在實現物件模型中出現oop/klass二分法的一個原因是我們不希望每個物件都有一個C++ vtbl指標。因此,正常的oops沒有任何虛擬函式。相反,他們將所有虛擬函式轉發給它們的klass,klass具有一個vtbl並根據物件執行C++排程實際型別。(有關轉發程式碼,請參閱oop.inline.hpp。).所有實現此排程的函式都以“oop_”為字首!

klass的層級結構:
klass繼承

四.klass和oop之間的聯絡

這裡寫圖片描述

所有的oop物件例項都會有一個指標,指向對應的instanceKlass,同時instanceKlass也會有一個instanceKlassKlass來描述它,這種鏈條直到KlassKlass終止.因為klassKlass的指標始終是指向自己的..參考內容
:這裡看大家原始碼的時候可能會有一個疑問,Klass_vtbl的原始碼中(就是Klass.hpp),沒有出現_mark和_metadata.在JDK8之前(本文章是基於JDK7),方法區內的描述型別的元資料物件,也是由GC管理的。所有由GC統一管理的物件,都要繼承自oopDesc,所以Klass都包含了頭資訊_mark和metadata。從JDK8開始,型別元資料都移出了GC堆,所以Klass這個屬性可以直接指向Klass類了。

後面還會出兩篇用HSDB和sa-jdi的tool去檢視物件模型的資料的文章,敬請期待~
參考資料:
1.深入理解多執行緒(二)—— Java的物件模型
2.HotSpotVM 物件機制實現淺析#1
3.借HSDB來探索HotSpot VM的執行時資料