JVM內存管理

這些日子一直在研究jvm內存管理的東西,網上的知識很多,總結一下,以備後用。

    首先,剛學java的時候就知道java類文件是以 .java爲後綴的文件,經過javac命令編譯後,編譯成class文件,class文件中都是二進制格式的數據,所以想要看編譯後的內容是什麼,可以採用jdk自帶的javap命令查看。

   記得剛學java的時候覺得java虛擬機厲害的很,java的風光正是建立在它的功勞之上。JVM (java vitual machine)。JVM中有個組成部分爲類加載器(ClassLoader),負責java文件編譯後class文件的加載,加載到哪呢,加載到內存。那下面來說一下JVM的內存管理。

JVM的內存分棧內存、堆內存、本地方法棧和方法區四部分。java通過類加載器來加載class文件,加載到內存後,會把類、方法、常變量放到堆內存中。因爲java是自動進行垃圾回收的,所以放入堆內存中的東西,哪些該回收,哪些不該回收?這都需要jvm去額外的線程去進行判斷。但如果對於一個大型的J2EE系統來說,當創建的對象及方法變量比較多時,即堆內存中的對象比較多,如果一個一個對象去進行循環判斷是否該回收時,這樣的回收機制未免太耗時了,系統的性能一定會下降,jvm爲了提高jvm執行效率,採用了堆內存分區管理的機制。

JVM把堆內存分三大塊:Young Generation Space 新生區(也稱新生代)、Tenure generation space養老區(也稱舊生代)、Permanent Space 永久存儲區。分區是爲了進行模塊化管理,管理不同的對象及變量以提高JVM的執行效率。

對於Young Generation Space ,它主要用來存儲新創建的對象,內存大小會比較小,垃圾回收會比較頻繁。對此區又分三個區域:一個Eden Space和兩個Survivor Space。有一個前輩對這三個區域描述的相當透徹:

  • 當對象在堆創建時,將進入年輕代的Eden Space。
  • 垃圾回收器進行垃圾回收時,掃描Eden Space和A Suvivor Space,如果對象仍然存活,則複製到B Suvivor Space,如果B Suvivor Space已經滿,則複製 Old Gen
  • 掃描A Suvivor Space時,如果對象已經經過了幾次的掃描仍然存活,JVM認爲其爲一個Old對象,則將其移到Old Gen。
  • 掃描完畢後,JVM將Eden Space和A Suvivor Space清空,然後交換A和B的角色(即下次垃圾回收時會掃描Eden Space和BSuvivor Space。

 對於Tenure generation space,它主要是用來存儲那些長時間被引用的對象。因爲它裏面存放的是經過幾次在Young Genderation Space 進行掃描判斷過仍存活的對象,內存大小會比較大,垃圾回收頻率會比較小。

 對於Permanent Space 永久存儲區,它是用來存儲一些值信息不經常變更的東東,有類定義、字節碼和常量等。


內存管理表:

1、分代GC策略

組成

詳解

堆(Heap)內存

 

JVM採用一種分代回收(generational collection)的策略,用較高的頻率對年輕的對象(young generation)進行掃描和回收,這種叫做minor collection,而對老對象(old generation)的檢查回收頻率要低很多,稱爲major collection。這樣就不需要每次GC都將內存中所有對象都檢查一遍,以便讓出更多的系統資源供應用系統使用。

非堆內存

 

GC不會在主程序運行期對PermGen Space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現PermGen Space錯誤。


2、 內存分配(申請)過程

步驟

操作

1

JVM會試圖爲相關Java對象在Eden中初始化一塊內存區域;

2

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

3

JVM試圖釋放對Eden中所有不活躍的對象minor collection,釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區;

4

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

5

當OLD區空間不夠時,JVM會在OLD區進行major collection;

6

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

 

3、對象衰老過程

步驟

操作

1

young generation的內存,由一塊Eden和兩塊Survivor Space構成。新創建對象的內存都分配自eden。兩塊Survivor Space總有會一塊是空閒的,用作copying collection的目標空間。Minor collection的過程就是將eden和在用survivor space中的活對象copy到空閒survivor space中。對象在young generation裏經歷了一定次數的minor collection後,年紀大了,就會被移到old generation中,稱爲tenuring。

2

剩餘內存空間不足會觸發GC,如eden空間不夠了就要進行minor collection,old generation空間不夠要進行major collection,permanent generation空間不足會引發Full GC。

 

GC觸發條件

GC類型 觸發條件 觸發時發生了什麼 注意 查看方式
YGC eden空間不足

清空Eden+from survivor中所有no ref的對象佔用的內存
將eden+from sur中所有存活的對象copy到to sur中
一些對象將晉升到old中:
    to sur放不下的
    存活次數超過turning threshold中的
重新計算tenuring threshold(serial parallel GC會觸發此項)

重新調整Eden 和from的大小(parallel GC會觸發此項)

全過程暫停應用
是否爲多線程處理由具體的GC決定
jstat –gcutil
gc log
FGC

old空間不足
perm空間不足
顯示調用System.GC, RMI等的定時觸發
YGC時的悲觀策略
dump live的內存信息時(jmap –dump:live)

清空heap中no ref的對象
permgen中已經被卸載的classloader中加載的class信息

如配置了CollectGenOFirst,則先觸發YGC(針對serial GC)
如配置了ScavengeBeforeFullGC,則先觸發YGC(針對serial GC)
全過程暫停應用
是否爲多線程處理由具體的GC決定

是否壓縮需要看配置的具體GC
jstat –gcutil
gc log
         permanent generation空間不足會引發Full GC,仍然不夠會引發PermGen Space錯誤。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章