Klass與Oop

前段時間,一直在看《Hotspot實戰》,順便編譯了一份OpenJDK的源碼,而後就在eclipse裏面調試起來。c++

雖然個人入門語言是c/c++,可是被Java拉過來好幾年了,如今再看源碼,熟悉又陌生,好在慢慢找到了感受。數據結構

這是分析Hotspot源碼的第一篇,講一下Klass和Oop這兩種數據結構。eclipse

系統的介紹和講解,能夠查看https://yq.aliyun.com/articles/20279和http://www.jianshu.com/p/252e27863822這兩篇文章。確實寫的比較好,深刻並且透徹。另外能夠再看看《Hotspot實戰》的第3章。oop

我這裏主要看看Klass和Oop的內存佈局。佈局

 

當時看這張圖的時候,有一個巨大的疑問,instanceKlass的數據結構與圖不符,沒有對象頭(Mark和Klass這兩個屬性)。this

真是百思不得其解。spa

因而,繼續看源碼。指針

1)對象頭裏的Klass這個屬性,是一個klassOopDesc類型的指針,並非一個指向Klass類的指針。why???調試

看了以前的第一篇文章,豁然開朗。在JDK8以前,方法區內的描述類型的元數據對象,也是由GC管理的。全部由GC統一管理的對象,都要繼承自oopDesc,因此纔會誕生klassOopDesc這個類型。從JDK8開始,類型元數據都移出了GC堆,因此Klass這個屬性能夠直接指向Klass類了。code

2)klassOopDesc只有從父類繼承過來的Mark和Klass這兩個屬性,並無指向Klass類的指針,那oop是如何找到對應的Klass的呢???

klassOopDesc內部有一個方法:klass_part()

 

  // returns the Klass part containing dispatching behavior
  Klass* klass_part() const                      { return (Klass*)((address)this + sizeof(klassOopDesc)); }

 

這個方法果真返回一個指向Klass的指針,可是計算過程比較詭異,在當前klassOopDesc對象的首地址增長sizeof(klassOopDesc)這麼多空間後的地址。也就是說,一個klassOopDesc對象數據和對應的Klass對象數據,是從上到下緊密的排列着,有了klassOopDesc的指針,就能順藤摸瓜找到對應的Klass數據。

那當初構造的時候,是按這種模式在內存分配數據的嗎???

以前的第二篇文章,講的鉅細。能夠看到,在類加載的過程當中,構造了一個空的Klass對象,而後調用了Klass類的as_klassOop方法返回klassOopDesc的指針。

  // returns the enclosing klassOop
  klassOop as_klassOop() const {
    // see klassOop.hpp for layout.
    return (klassOop) (((char*) this) - sizeof(klassOopDesc));
  }

klassOop是klassOopDesc指針的一個別名。構造的時候,首地址減去sizeof(klassOopDesc)這麼多空間後的地址。這時候,內存空間是分配出來了,具體的數據,在後續過程當中填充。

最後說下看源碼心得體會 :其實那張圖上的數據排列結構是對的,可是具體的實現方式,若是不看源碼確定會很疑惑。另外,看到這麼犀利的指針操做,對c/c++的好感真是倍增。

相關文章
相關標籤/搜索