Java 對象在堆中的內存結構


​http://blog.csdn.net/renfufei/article/details/14669513

 
翻譯人員: 鐵錨
翻譯日期: 2013年11月8日
原文鏈接:   What do Java objects look like in memory during run-time?

我們知道,函數每次被調用時,在內存中都有自己的活動記錄(activation record),稱為棧空間(stack). Java 的方法在調用時在 JVM 棧中為其分配一個棧幀(Java棧空間的一個片段),可以稱之為方法棧. 原則上,所有對象都在堆空間(Heap)中分配.

java對象在內存中是怎樣分配的呢? 一旦對象在堆中分配了空間,那本質上就是一系列的字節. 那么如何找到對象中某個特定的屬性域呢? 編譯器通過一個內部表來保存每個域的偏移量.

下圖是 Base 類的一個對象內存分布圖,Base(基類)沒有定義任何方法,關於方法在內存中的分布請看接下來的內容.


圖1
如果還有另一個派生類 "Derived" 繼承了基類"Base".那么內存分布將如下圖所示:

圖2
子類對象和父類對象擁有同樣的內存分布,當然,子類對象需要更多的空間來存放新的屬性域.
這種分配方式的好處在於 Base類型的指針 如果指向了子類Derived的對象, 依然在開頭的地方"看見"Base對象.
因此, 子類對象(Derived)采用 父類引用(Base) 來進行的操作 保證是安全的,因此在運行時不需要動態地檢查 Base 引用的實際類型.
用樣的道理,方法也可以放到object空間的開始處,如下圖所示.

圖3

然而這種實現方式是沒有效率的.假若一個類有很多方法(例如20個),那么每個對象就要持有20個指針,相應的,每個對象都需要20個指針的內存空間,這會導致創建對象變慢,所占空間更大。
優化手段是創建一個  虛擬函數表(vtable,虛表),虛表是一個指向特定類的成員函數的指針數組. 如下圖所示:

圖4

* 以上是我對斯坦福大學編譯器講座所做的筆記,該講座非常生動有趣。
參考文獻:
1.  Stanford Compilers Lectures
2.   JVM
相關文章:

    1. What does a Java array look like in memory?
    2. Top 5 Questions about C/C++ Pointers
    3. 簡述Java內存泄露
    4. An example of C++ dot vs. arrow usageYarpp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM