java的對象模型

java中的對象在內存中,到底是怎樣一種存在?java

這篇隨筆,咱們就來一探究竟。可能不夠深刻,可是咱們把理解到位,深刻到咱們須要的程度這樣便可。c++

先來看下jvm的內存模型:git

程序計數器github

虛擬機棧和本地方法棧jvm

ide

方法區(運行時常量池)oop

(圖片出處:https://howtodoinjava.com/java/garbage-collection/jvm-memory-model-structure-and-components/)lua

這就是整個的jvm的內存模型的組成部分,那麼對象是存儲在Heap Area中的,也就是堆空間。spa

知道了存儲的地方,那具體到底是怎麼存儲的呢?咱們繼續。指針

注:全篇所說的jvm都是特指HotSpot JVM。

(剛在看OOP_CLASS)的過程當中,詳細看了一篇博客寫的很清晰,把相關的內容寫的很清晰。看了下介紹是個15年畢業的兄弟,如今已是阿里的技術專家了,再次印證的那個道理,人必須有個勤字,一勤天下無難事,還有就是恆字,檢討我本身的技術生涯,若是能作到這兩個字也早起來了。痛定思痛繼續努力。

以前其實翻過HotSpot的Klass部分的源碼,但當時並無深入的理解,今天再來引用一下。

先看整個的結構:

Java對象分爲兩個部分在jvm中,一個是對象自己,一個是對象對應的類,在jvm的代碼oopsHierarchy.hpp中能夠看到,表明對象的是下邊這些:

#ifndef CHECK_UNHANDLED_OOPS

typedef class oopDesc*                            oop;
typedef class   instanceOopDesc*            instanceOop;
typedef class   methodOopDesc*                    methodOop;
typedef class   constMethodOopDesc*            constMethodOop;
typedef class   methodDataOopDesc*            methodDataOop;
typedef class   arrayOopDesc*                    arrayOop;
typedef class     objArrayOopDesc*            objArrayOop;
typedef class     typeArrayOopDesc*            typeArrayOop;
typedef class   constantPoolOopDesc*            constantPoolOop;
typedef class   constantPoolCacheOopDesc*   constantPoolCacheOop;
typedef class   klassOopDesc*                    klassOop;
typedef class   markOopDesc*                    markOop;
typedef class   compiledICHolderOopDesc*    compiledICHolderOop;

#else

表明類的是下邊這些:註釋上也寫了,klass的結構和oop的結構是分開的

// The klass hierarchy is separate from the oop hierarchy.

class Klass;
class   instanceKlass;
class     instanceMirrorKlass;
class     instanceRefKlass;
class   methodKlass;
class   constMethodKlass;
class   methodDataKlass;
class   klassKlass;
class     instanceKlassKlass;
class     arrayKlassKlass;
class       objArrayKlassKlass;
class       typeArrayKlassKlass;
class   arrayKlass;
class     objArrayKlass;
class     typeArrayKlass;
class   constantPoolKlass;
class   constantPoolCacheKlass;
class   compiledICHolderKlass;

#endif // SHARE_VM_OOPS_OOPSHIERARCHY_HPP

爲何要分開,聽說是爲了不像c++那樣實現多態的時候須要每一個對象維護一個虛方法表,而分開的。這樣oopDesc裏咱們能夠看到,對象的定義裏,對象頭除了MarkWord以外,就是類型指針,而類型指針其實就是方法區的instanceKlass。表示的就是類在jvm裏的實例信息。

代碼連接:https://github.com/openjdk-mirror/jdk7u-hotspot/blob/50bdefc3afe944ca74c3093e7448d6b889cd20d1/src/share/vm/oops/oopsHierarchy.hpp

class oopDesc {
  friend class VMStructs;
 private:
  volatile markOop  _mark;  // 1 MarkWord
  union _metadata { // 2 類型指針
    wideKlassOop    _klass;
    narrowOop       _compressed_klass;
  } _metadata;
 
// ...省略
private: // field addresses in oop void* field_base(int offset) const; jbyte* byte_field_addr(int offset) const; jchar* char_field_addr(int offset) const; jboolean* bool_field_addr(int offset) const; jint* int_field_addr(int offset) const; jshort* short_field_addr(int offset) const; jlong* long_field_addr(int offset) const; jfloat* float_field_addr(int offset) const; jdouble* double_field_addr(int offset) const; address* address_field_addr(int offset) const;

這個就是OopDesc.hpp的代碼,而咱們要的InstanceOop是這樣的

#include "oops/oop.hpp"

// An instanceOop is an instance of a Java Class
// Evaluating "new HashTable()" will create an instanceOop.

class instanceOopDesc : public oopDesc {
 // 省略
};

#endif // SHARE_VM_OOPS_INSTANCEOOP_HPP

明顯看到instanceOopDesc就是繼承自oopDesc的。因此咱們來分析下oopDesc的結構。

咱們知道Java對象的組成部分是:對象頭(Header)/ 實例數據(Instance Data)/ 對齊填充(Padding) 三個部分。而對象頭又包括兩部分:MarkWord 和 類型指針。

代碼中明顯能夠看到對象頭的部分,咱們已經標註出來,而實例數據就在下邊的各類field裏。

看到了OopDesc表示的對象,咱們再來看下Klass表示的類吧。

相關文章
相關標籤/搜索