翻譯人員: 鐵錨
翻譯日期: 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
相關文章:
- What does a Java array look like in memory?
- Top 5 Questions about C/C++ Pointers
- 簡述Java內存泄露
- An example of C++ dot vs. arrow usage