內存管理和垃圾回收是JVM非常關鍵的點,對Java性能的剖析而言,了解內存管理和垃圾回收的基本策略非常重要。
1.在程序運行過程當中,會創建大量的對象,這些對象,大部分是短周期的對象,小部分是長周期的對象,對於短周期的對象,需要頻繁地進行垃圾回收以保證無用對 象盡早被釋放掉,對於長周期對象,則不需要頻率垃圾回收以確保無謂地垃圾掃描檢測。為解決這種矛盾,Sun JVM的內存管理采用分代的策略。
1)年輕代(Young Gen):年輕代主要存放新創建的對象,內存大小相對會比較小,垃圾回收會比較頻繁。年輕代分成1個Eden Space和2個Suvivor Space(命名為A和B)
當對象在堆創建時,將進入年輕代的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。
我們可以看到:Young Gen垃圾回收時,采用將存活對象復制到到空的Suvivor Space的方式來確保不存在內存碎片,采用空間換時間的方式來加速內存垃圾回收。
2)年老代(Tenured Gen):年老代主要存放JVM認為比較old的對象(經過幾次的Young Gen的垃圾回收后仍然存在),內存大小相對會比較大,垃圾回收也相對沒有那么頻繁(譬如可能幾個小時一次)。年老代主要采用壓縮的方式來避免內存碎片 (將存活對象移動到內存片的一邊),當然,有些垃圾回收器(譬如CMS垃圾回收器)出於效率的原因,可能會不進行壓縮。
3)持久代(Perm Gen):持久代主要存放類定義、字節碼和常量等很少會變更的信息
2.總結
1、對象優先在Eden分配,這里大部分對象具有朝生夕滅的特征,Minor GC主要清理該處
2、大對象(占內存大)、老對象(使用頻繁)
3、Survivor無法容納的對象,將進入老年代,Full GC的主要清理該處
3.JVM有 2個GC線程
第一個線程負責回收Heap的Young區
第二個線程在Heap不足時,遍歷Heap,將Young 區升級為Older區
JVM(采用分代回收的策略),用較高的頻率對年輕的對象(young generation)進行YGC,而對老對象( tenured generation)較少( tenured generation 滿了后才進行)進行Full GC。這樣就不需要每次GC都將內存中所有對象都檢查一遍。
GC不會在主程序運行期對PermGen Space進行清理,所以如果你的應用中有很多CLASS(特別是動態生成類,當然permgen space存放的內容不僅限於類)的話,就很可能出現PermGen Space錯誤。
4.jvm的調優
減少FullGC的次數,以為FullGC會暫停程序比較長的時間,如果FullGC的次數比較多。程序就會經常性的假死。
Heap size 設置
JVM 堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可進行設置。
如果Heap size 設置偏小,GC占用了更多的時間,而應用分配到的執行時間較少。但Heap size 最大不要超過可用物理內存的80%。
具有2G或者更多的物理內存
http://www.xuebuyuan.com/1201516.html