jvm記憶體的劃分:
堆 |
棧 |
未初始化 |
初始化 |
正文段 |
粗略的說,jvm記憶體大緻分兩塊:堆heap和非堆permanent;
從英文翻譯上看,非堆permanent是“持久”的意思,它應該是存儲需要持久存在的資料,而堆heap相對的就是不持久的資料區;
但我怎麼感覺堆heap才是持久的資料區呢?你看非堆permanent中的“棧”跟“客棧”一個字,客棧明顯住不長久,還怎麼持久???????
具體如何:
堆heap: 存儲所有的類執行個體,為數組記憶體配置設定空間;堆分為:young generation 和 old generation;
young generation: 1*(eden sapce) + 2*(Surviver space)(from、to)
Eden:伊甸園 ------- 存放新生的對象(new 對象)
Surviver:存活者 ------- 經曆過垃圾回收後存活下來的對象
old generation: 存放生命周期長的對象;
非堆permanent: 存儲java的類資訊,包括解析後得到的方法、屬性、字段等;不參與垃圾回收;
JVM記憶體申請過程如下:
- JVM 會試圖為相關Java對象在Eden中初始化一塊記憶體區域
- 當Eden空間足夠時,記憶體申請結束;否則到下一步
- JVM 試圖釋放在Eden中所有不活躍的對象(這屬于1或更進階的垃圾回收),釋放後若Eden空間仍然不足以放入新對象,則試圖将部分Eden中活躍對象放入Survivor區
- Survivor區被用來作為Eden的old的中間交換區域,當old區空間足夠時,Survivor區的對象會被移到old區,否則會被保留在Survivor區
- 當old區空間不夠時,JVM 會在old區進行完全的垃圾收集(0級)
- 完全垃圾收集後,若Survivor及old區仍然無法存放從Eden複制過來的部分對象,導緻JVM無法在Eden區為新對象建立記憶體區域,則出現”out of memory”錯誤
1、堆是在程式運作時,而不是在程式編譯時,申請某個大小的記憶體空間。即動态配置設定記憶體,對其通路和一般記憶體的通路沒有差別。
2、堆是應用程式在運作的時候請求作業系統配置設定給自己記憶體,一般是申請/給予的過程。
3、堆是指程式運作時申請的動态記憶體,而棧隻是指一種使用堆的方法(即先進後出)。
關于棧:
Java棧是與每一個線程關聯的,JVM在建立每一個線程的時候,會配置設定一定的棧空間給線程。它主要用來存儲線程執行過程中的局部變量,方法的傳回值,以及方法調用上下文。棧空間随着線程的終止而釋放。
Java堆是被所有線程共享的;
現在看來,我感覺jvm的分類應該再擴充下,分:堆、非堆、棧,我把java代碼需要加載的東西分為:類源碼、類對象(new)、類源碼方法、類源碼變量、對象方法、對象變量、參數;
類源碼----------------------->非堆
源碼方法----------------------->非堆
源碼變量----------------------->非堆
類對象--------------------------->堆
對象方法--------------------------->堆
對象變量--------------------------->堆
參數---------------------------------->棧
全局變量(成員變量)是在建立對象的時候配置設定記憶體;
點評:其實類源碼包括了源碼方法、源碼變量,類對象包括了對象方法、對象變量;這樣再分出來的确多此一舉。但這是為了自己更好一一對照、強調,純屬個人習慣... ...
java中的類大緻分為三種(這是摘錄别人的):
1.系統類
2.擴充類
3.由程式員自定義的類