天天看點

JVM的記憶體管理

今天通過無意中看到了String類的intern()方法,意義是把這個String放入到運作時常量池。回顧了一下 深入java虛拟機 這本書,總結一下jvm的記憶體管理

方法區(Permanent Generation) [color=red]VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M[/color]。運作時常量池,類和方法的位元組碼檔案的存儲都在這個區。 這個區有些文章說沒有GC,但是實際上現代的JVM也會對這個區進行GC,隻是頻率很低。 Spring會利用代理技術來支援AOP,産生的代理對象也在這個區。

VM棧(stack) [color=red]VM Args:-Xss[/color] 線程運作的棧區,包括方法執行的幀(frame)和臨時變量。32位系統如果不設定的話,預設是10M(待确認)

堆(Heap) [color=red]VM Args:-Xms20m -Xmx20m[/color] 存放對象執行個體,為所有線程共享

關于堆又被劃分為新生代(young generation)和舊生代(old generation)。 新生代又被隔離為(eden, survivor A, survivor B),這麼劃分的目的主要是為了防止記憶體碎片,通過複制收集算法來回收記憶體。 因為程式執行過程中會産生很多臨時對象,而其中的大部分一次用完就基本沒用了。是以如果eden區在不能滿足要配置設定對象的空間的時候,就會觸發一次minor GC。 minor GC掃描eden區,把繼續存活的對象拷貝到Survivor A中。如果survivor區域的空間不夠大,則直接拷貝到舊生代中

[color=red]VM參數:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8[/color]通過配置設定byte[]來測試觸發minor GC。 另外在eden經過GC後存活,并且survivor能容納的對象,将移動到survivor空間内,如果對象在survivor中繼續熬過若幹次回收(預設為15次)将會被移動到舊生代中。在Minor GC觸發時,會檢測之前每次晉升到老年代的平均大小是否大于老年代的剩餘空間,如果大于,改為直接進行一次Full GC,如果小于則檢視HandlePromotionFailure設定看看是否允許擔保失敗,如果允許,那仍然進行Minor GC,如果不允許,則也要改為進行一次Full GC。