Java 面試- JVM 的Stack 和Heap - Laugh Now
文章推薦指數: 80 %
Heap 是Class Type 創建實例時存放資料的地方,在Heap 創建完成後會回傳所在的記憶體位址。
變數可能是Primitive Type 或Class / Reference Type 。
若是 ...
HomeArchivesCategoriesTagsAbout2016-09-14發表2021-03-07更新Technique / Java12分鐘讀完(大約1852個字)Java面試-JVM的Stack和Heap請比較JVM記憶體的Stack和Heap這題非常容易考到,而且翻譯十分混亂,盡量用原文去表達比較好,Stack繁中為堆疊、簡中為棧,Heap繁中為堆積、簡中為堆。
要特別注意的是,這邊的Stack和Heap並不是在指資料結構,而是指JVM記憶體管理的部分。
聲明:這些內容比較簡略、粗糙,忽略了很多細節,只揀選能回答到問題的部份去解說,並不是百分之百準確,除非每一題都有兩個小時以上的回答時間,否則這些內容應該足夠回答到面試官想聽的點。
如果你真的很在乎每一個部份的細節內容,你不該讀我的筆記,而是去讀文件,自己寫自己的筆記。
當然,我會隨著越講越深入而帶入更多細節的部份,但是我也需要考量文章篇幅以及流暢度。
若有任何錯誤或遺漏之處,請在底下用力鞭我,不用客氣,隱瞞缺失比直指痛處更讓人害怕。
首先,Java檔經過編譯後所產生的Class檔(bytecode),只能運行在JVM上,而JVM在運算時,如同一般電腦一樣,需要記憶體儲存運算所需的資料及指令,而JVM記憶體中的Stack和Heap最常被拿來做比較(記憶體中當然還有其他部份,包括MethodArea、PCRegister、NativeMethodStack,但不在本篇討論範圍)。
JVM記憶體的Stack和Heap絕對不要和其他同名的東西搞混,在這裡是做為JVM儲存資料或指令的區域,和其他同名的東西無關,請把它當作平行宇宙看待。
Java中的資料型態分為兩種:PrimitiveType基本型態共有8種:int、short、long、byte、float、double、boolean、char。
這種類型是通過如inta=3;longb=123L;的方式宣告。
長度及生命週期都為可知(程式碼區塊執行完就扔掉)。
運算速度快,但長度與內容受限。
ClassType/ReferenceType類別型態/參考型態其他大都屬於此類別,如Integer、String、Long以及自行定義的類別(ex.User)等。
這種類型通常都需要用new去創建,如Useruser=newUser("Mark");。
因為是在執行時才動態創建,所以長度及生命週期都不可預知。
靈活但運算較耗時。
Stack堆疊、棧複習一下前一章所提到的:每一個Thread擁有自己的Stack,Stack是用來儲存函數路徑及區域變數,Thread之間的Stack互相獨立。
Stack是一種後進先出(FILO)的容器,具有存取速度快和管理簡單的特點。
由於Java中變數跟函式的生命週期都為後進先出,也就是越晚產生的會越先被回收或銷毀,所以Stack非常適合做為這種可預測性的資料,如區域變數、函式參數與函式返回位址等等,的儲存容器。
因為Stack中的資料生命週期都是規律的,所以由系統自行去產生和回收空間即可,程式設計師不需要介入。
Heap堆積、堆還記得前一章提到Process的MemorySpace是專門儲存共享資料/資源的嗎?Heap就屬於這種共享資料。
ClassType在創建實例(Instance)時(ex.newUser("Mark");),就是把資料放置於Heap中,系統會在Heap內找一塊區域放置此User實例的屬性資料,也因為Heap存放的是共享資料,所以不論該實例是由哪一個Thread所創建的,同Process底下的其他Thread也可以進行存取。
因為實例的生命週期是不可預知的,系統較難以自行去回收空間,所幸,Java的特色之一就是GarbageCollection機制(簡稱GC)**,會自動去清理Heap內已經沒有被參考(Reference)**的資料,當然,程式設計師可以撰寫程式去控制GC的行動,不過大多數情況下都不建議如此,過多的介入反而可能造成資源的浪費,未來可能會再寫一篇簡述GC是如何判斷哪些資料應該被清理。
範例可能有人看到這邊仍是霧煞煞,以下我用簡單的程式來講解資料儲存實際上是如何運作。
123inta=123;longb=456L;Userc=newUser("Mark",Gender.MALE);以上程式碼的資料儲存順序大致上可以視為以下流程圖*(在此先不考慮ConstantPool)*。
前兩行指令都是PrimitiveType,會在Stack內建立變數a和b,並將實際值123和456L存放於變數內。
第三行指令要切分成兩個部份,等號右邊及左邊,首先是右邊的部份,先以name和gender參數創建一個User實例,此時會在Heap中的一個位址(ex.0x1234)存放實例的屬性資料(ex.name、gender、address…),並將實例所在的記憶體位址(0x1234)指定給變數c參考。
這篇是以變數為例子去比較兩者儲存方式的不同,至於「Stack如何儲存函式」、「常數池(ConstantPool)是什麼」、「實例的method存放在哪」等等問題,留待後面文章再做解答。
從以上的例子可以發現,Stack內的變數值分為兩種類型,一種為ValueType實質類別,儲存的是實際的值(ex.123、456L);另一種為ReferenceType參考類別,儲存的是資料在Heap中的記憶體位址(ex.0x1234)。
總結Stack和Heap是JVM記憶體儲存資料或指令的區域。
Java的資料類型分為兩種:PrimitiveType和ClassType。
Stack存取速度快,但資料長度及生命週期必須是預知的,用來儲存區域變數、函式參數與函式返回位址等資料。
Heap是ClassType創建實例時存放資料的地方,在Heap創建完成後會回傳所在的記憶體位址。
變數可能是PrimitiveType或Class/ReferenceType。
若是PrimitiveType,則在Stack內的變數值為實際值;若是Class/ReferenceType,實例資料會儲存在Heap中,Stack內的變數值為實例在Heap中的記憶體位址。
Useruser=newUser("Mark");的行為簡單來說是:i.創建並儲存User實例(name=Mark)於Heap中。
ii.儲存完成後,回傳資料所在的記憶體位址。
iii.在Stack中新增變量user。
iv.將ii.所傳回的記憶體位址指定給user參考。
#interviewjvmstackheapStructuresandArchitecturesforOptimizingDatabase(EN)Java面試-Program、Process和Thread評論markleetwProductManager/EngineerTaipei,Taiwan文章22分類11標籤40追蹤最新文章2021-02-18透過Gmail收發個人網域的電子郵件Technique/Misc2020-05-31《生時間》讀書心得筆記Reading2017-12-09製作一支應聲蟲LineBotTechnique/Python2017-10-13Shebang:*nix的使用預設程式執行Technique/Linux2017-01-28StructuresandArchitecturesforOptimizingDatabase(EN)Technique/Database×
延伸文章資訊
- 11.4.2 Heap Tree - 資料結構&演算法筆記 - GitBook
- 2stack和heap的區別@ 程式專欄 - 隨意窩
其操作方式類似於數據結構中的棧。2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收。注意它與數據結構中的堆是兩回事, ...
- 3Stack 與Heap 有何差別. 程式設計相關的行業 - Medium
什麼叫做Heap ? Heap 是一種保留一大塊夠用的記憶題,讓程式方便配置它所需要的資料。真的顧名思義, Heap 就是堆放空間的意思。程式可以有許多 ...
- 4堆積- 維基百科,自由的百科全書 - Wikipedia
堆積(英語:Heap)是電腦科學中的一種特別的完全二元樹。若是滿足以下特性,即可稱為堆積:「給定堆積中任意節點P和C,若P是C的母節點,那麼P的值會小於等於(或大於 ...
- 5記憶體- stack 與heap - iT 邦幫忙::一起幫忙解決難題