JVM內存詳解

內存組成

這裏寫圖片描述

內存區主要可以劃分爲5個區域,如上圖。

  • java堆(Heap)
    這裏寫圖片描述
    堆內存是運行時的數據區域。有新生代和舊生代組成,存儲new對象的地方。這塊是GC的主要區域。從存儲的內容我們可以很容易知道,方法區和堆是被所有java線程共享的。
    持久帶PermGen space屬於非堆內存,是指內存的永久保存區域。這塊內存主要是被JVM存放Class和Meta信息的。Class在被Loader時就會被放到PermGen space中,它和存放類實例的堆內存區域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應用中有很CLASS的話,就很可能出現PermGen space錯誤,這種錯誤常見在web服務器對JSP進行pre compile的時候。如果你的應用程序下用了大量的第三方jar, 其大小超過了jvm默認的大小(4M)那麼很可能就會產生PermGen space溢出的異常了。

  • 方法區(Method Area)
    用於存儲應用程序的所有類結構信息,雖然JVM規範把方法區描述爲堆的一個邏輯部分,但它屬於非堆內存。存儲信息包括常量池、靜態變量、構造函數等。它是在 Java 虛擬機啓動時創建,由所有線程共享。

  • JVM棧(Stack)
    這裏寫圖片描述
    JVM棧總是和線程關聯在一起,每當創建一個線程時,JVM就會爲這個線程創建一個對應的java線程棧。
    在這個java棧中又會包含多個棧幀,每運行一個方法就創建一個棧幀,每個棧幀對應着當前線程棧對每個方法的每次調用。方法從調用直至執行完成的過程,就對應一個棧幀在java棧中入棧到出棧的過程。所以java棧是每個線程私有的,線程生就生,線程滅就滅。棧中的棧幀隨着方法的結束也會撤銷,內存自然就跟着回收了。
    棧幀又分爲局部變量區和操作數棧兩部分。局部變量區用於存放方法中的局部變量和參數;操作數棧用於存放方法執行過程中產生的中間結果;每個線程棧大小, JDK1.5+ 默認大小爲 1M。一般來說如果棧不是很深的話, 1M 是絕對夠用了的。

  • 程序計數器(PC Register)
    用於保存當前線程執行的內存地址。由於JVM程序是多線程執行的(線程輪流切換),所以爲了保證線程切換回來後,還能恢復到原先狀態,就需要一個獨立的計數器,記錄之前中斷的地方,可見程序計數器也是線程私有的。

  • 本地方法棧(Native Method Stack)
    和java棧的作用差不多,只不過是爲JVM使用到的native方法服務的。

回收算法和過程

當一個URL被訪問時,內存申請過程 如下:
(1)JVM會試圖爲相關Java對象在Eden中初始化一塊內存區域。

(2) 當Eden空間足夠時,內存申請結束。否則到下一步。

(3)JVM試圖釋放在Eden中所有不活躍的對象(這屬於1或更高級的垃圾回收), 釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區。

(4)Survivor區被用來作爲Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,否則會被保留在Survivor區。

(5)當OLD區空間不夠時,JVM會在OLD區進行完全的垃圾收集(0級)。

(6)完全垃圾收集後,若Survivor及OLD區仍然無法存放從Eden複製過來的部分對象,導致JVM無法在Eden區爲新對象創建內存區域,則出現”out of memory錯誤。

友情鏈接:http://blog.csdn.net/tonytfjing/article/details/44278233

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章