1. 程式人生 > >java對象的內存布局

java對象的內存布局

clone 調用父類 常見 clas new 如果 編譯器 java對象 內存布局

  • 在Java程序中,我們擁有多種新建對象的方式。除了最為常見的new之外,我們還可以通過反射機制、反序列化、object.clone方法以及Unsafe.allocateInstance方法來新建對象
  • Object.clone方法和反序列化通過直接復制已有的數據,來初始化新建對象的實例字段。Unsafe.allocateInstance方法則沒有初始化實例字段,而new語句和反射機制,則是通過調用構造器來初始化實例字段
  • 以new語句為例,它編譯而成的字節碼將包含用請求內存的new指令,以及用來調用構造器的invokespecial指令
    //Foo foo = new Foo(); 編譯而成的字節碼
    0 new Foo
    4 invokespecial Foo()
    7 astore_1
    

      

  • 提到構造器,就不得不提到java對構造器的諸多約束。首先,如果一個類沒有定義任何構造器的話,java編譯器會自動添加一個無參數的構造器
    // Foo類構造器會調用其父類的Object的構造器
    public Foo();
     0 aload_0[this]
     1 invokespecial java.lang.Object() [8]
     4 return
    

      

  • 然後,子類的構造器需要調用父類的構造器。如果父類存在無參數構造器的話,該調用可以是隱式的,也就是說java編譯器會自動添加對父類構造器的調用。但是,如果父類沒有無參數構造器,那麽子類的構造器需要顯式地調用父類帶參數的構造器
  • 顯式調用又可以分為兩種,一是直接使用“super”關鍵字調用父類構造器,二是使用“this”關鍵字調用同一個類中的其他構造器。無論是直接的顯式調用,還是間接的顯式調用,都需要作為構造器的第一條語句,以便優先初始化繼承而來的父類字段。(不過這可以通過調用其他生成參數的方法,或者字節碼註入來繞開。)

java對象的內存布局