深入JVM內核---JVM內存模型

        在上一篇博客中講GC算法的時候提到了一些關於JVM內存模型.JVM中用heap堆來存儲運行時的數據,所有類實例和數組由堆分配內存,JVM啓動時創建堆(heap memory),在堆以外的內存叫非堆(non-heap memory)


1.堆(Heap space)

在JVM的堆內存空間中,從大的層面劃分,可以分爲新生代(Young)和老年代空間(Old).其中Young空間又被分爲兩個部分和3個板塊,分別爲1個Egen區和2個survivor區.

Minor GC

從年輕代空間(包括Egen和survivor區域)回收內存被稱爲Minor GC.每次Minor GC會清理年輕代的內存.



Eden區域:

         是用來存放使用new或者newInstance等方式創建的對象,默認都是存放在Eden區,除非這個對象太大,或者超過了設定的閾值-XX:PretenureSizeThresold,這樣的對象會被直接分配到Old區域。 


Survivor(倖存)區

          一般稱S0,S1,理論上他們是一樣大的,解釋一下,他們是如何工作的: 在不斷創建對象的過程中,Eden區會滿,這時候會開始做Young G也叫Minor GC,而Young空間的第一次GC就是找出Eden區中,倖存活着的對象,然後將這些對象,放到S0,或S1區中的其中一個, 假設第一次選擇了S0,它會逐步將活着的對象拷貝到S0區域,但是如果S0區域滿了,剩下活着的對象只能放old區域了,接下來要做的是,將Eden區域 清空,此時時候S1區域也是空的。 


當第二次Eden區域滿的時候,就將Eden區域中活着的對象+S0區域中活着的對象,遷移到S1中,如果S1放不下,就會將剩下的部門,放到Old區域中,只是這次對象來源區域增加了S0,最後會將Eden區+S0區域,清空 


第三次和第四次依次類推,始終保證S0和S1有一個是空的,用來存儲臨時對象,用於交換空間的目的,反反覆覆多次沒有被淘汰的對象,將會放入old區域中,默認是15次,計數器會在對象的頭部記錄它交換的次數。


老年代(Old)

用於存放經過多次新生代GC仍然存活的對象。新建的對象也可能直接進入老年代,比如大對象(可通過參數指定)和大的數組對象。

永恆代(Perment)

存放類的Meta信息。

Major GC

是清理老年代.

Full GC

是清理整個堆空間---包括年輕代和老年代.

發生在老年代的GC,當老年代沒有足夠的空間時即發生Full GC.在這裏可能會發生Stop-The-World,這是java中一種全局暫停的現象,所有java代碼停止,native代碼可以執行,但不能和JVM交互.多半由於GC引起:Dump線程;死鎖檢查;堆Dump.


2.方法區:

用來儲存已經加載的類信息,常量,靜態變量以及方法代碼.


3.Java虛擬機棧

也叫棧區。是由一個個棧幀組成的後進先出的棧式結構,棧幀中存放方法運行時的局部變量、方法出口等信息。當調用一個方法時,就會在虛擬機棧中創建一個棧幀用於存放這些數據,方法調用完時棧幀消失。若方法中又調用了其他方法,則繼續在棧頂創建新的棧.


4.本地方法棧

與虛擬機棧類似,區別是本地方法棧是爲Native方法服務的,而java虛擬機棧是爲java方法服務的.

5.程序計數器

最小的一塊內存,通過改變計數器的值來選取下一條需要執行的字節碼指令.程序計數器用來爲線程獨立擁有,線互補互補影響,保證線程切換後能準確恢復到執行位置,線程執行指令的跳轉、循環、分支都要依賴計數器來完成.


發佈了153 篇原創文章 · 獲贊 588 · 訪問量 75萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章