Java 虚拟机内存分配与回收策略
垃圾收集器與內存分配策略參考目錄:
1.判斷 Java 對象實例是否死亡  
 2. Java 中的四種引用  
 3.垃圾收集算法  
 4. Java9 中的 GC 調優  
 5.內存分配與回收策略 
一、對象優先在 Eden 分配
在大多數的情況下,對象在新生代 Eden 區中分配內存空間。當 Eden 區沒有足夠的空間進行分配時,這時虛擬機將執行一次 Minor GC,由于 Eden 區沒有足夠的內存空間大小分配對象,對象會先考慮在新生代中的 Survivor 區分配空間,如果 Survivor 區中也沒有足夠的空間大小為對象分配內存,那么就會通過分配擔保策略將對象提前轉移到老年代中去。
二、大對象直接進入老年代
大對象是指需要大量連續內存空間的對象,最典型的就是數組以及很長的字符串。大對象對虛擬機的內存分配來說是一個壞消息,但是更糟糕的是你創建了一個生命周期很短的大對象 (這點我們在寫程序時要格外的注意),因為這樣容易導致內存中還有不少的空間時就得提前進行垃圾收集以騰出足夠大的連續內存空間來安置大對象。
虛擬機提供了一個 -XX:PretenureSizeThreshold 參數,令大于這個設置值的對象直接在老年代進行分配內存。
這樣做可以可以避免在 Eden 區與兩個 Survivor 區之間發生大量的內存復制 (新生代使用復制算法進行垃圾回收,如果你創建了一個大對象并且它的生命周期較長,在新生區發生垃圾回收是非常頻繁的,這就意味著你創建的大對象在執行 GC 時就需要被復制很多次,這樣做是非常不好的)。
三、長期存活的對象將進入老年代
虛擬機使用了分代收集的思想來管理內存,那么再進行垃圾回收時就必須能夠識別哪些對象需要放在老年代,哪些對象需要放在新生代。除了大對象直接進入老年代外,虛擬機還給每個對象定義了一個對象年齡 (Age) 計數器。
它將作為新生區對象進入老年代的一個標志,如果對象在 Eden 區被分配內存并經過一次 Minor GC 后成功存活下來,并且能夠在被 Survivor 區鎖容納,那么它的對象年齡就會加。
對象每“熬過”一次 Minor GC 那么它的年齡就會增加 1,這個年齡有個限制,就是當它的年齡增加到 15 歲時就會被晉升到老年代中去。這一點你可以設置這個年齡閾值,規定它的年齡超過這個閾值時就進入老年代,使用 -XX:MaxTenuringThreshold 進行設置。
四、動態對象年齡判定
當然虛擬機并不是全部要求對象的年齡必須到達 MaxTenuringThreshold 才被分配到老年代,為了更好的適應不同程序的內存情況,虛擬機還規定如果在 Survivor 中相同年齡的所有對象的大小的總和大于 Survivor 空間的一半,年齡大于或這等于該對象年齡的對象就可以直接進入到老年代。
五、空間分配擔保
在執行 Minor GC 之前,虛擬機會先檢查老年代中最大可用的連續空間是否大于新生代所有對象的總空間,如果這個條件成立,那么 Minor GC 就被視為是安全的。
如果條件不成立,則虛擬機會先查看 HandlePromotionFailure 設置值是否允許擔保失敗 (就像買了保險一樣,如果你承擔我執行后的風險我就執行,如果你不承擔我就不執行)。
在允許的情況下,那么虛擬機會繼續檢查老年代中最大可用的連續空間是否大于歷次晉升到老年代對象的平均大小,如果大于,那么就會嘗試著進行一次 Minor GC ,盡管這次執行是有風險的,如果小于或者 HandlePromotionFailure 為不允許那么就不能執行 Minor GC 轉為執行 Full GC。
這個風險指的是如果新生代中對象在執行一次 Minor GC 之后,另一塊 Survivor 區無法為所有活下來的對象的拷貝分配內存,那么就會在老年代中進行內存分配,在極端的情況下,如果在老年代中也沒有足夠的連續的內存空間為這些對象分配內存,老年代的內存就會溢出。
六、什么時候執行 Minor GC 與 Full GC
Minor GC
當新生代中的 Eden 區分配滿的時候觸發。讀了這篇博文你就會知道,隨著 Minor GC 的執行,老年代的空間通常會隨著 Minor GC 的執行內存占用空間增大。
Full GC
在將要執行 Minor GC 時如果老年代中最大可用的連續空間小新生代所有對象的總空間,這時會繼續檢查老年代中最大可用的連續空間是否大于歷次晉升到老年代對象的平均大小。
如果大于,并且 HandlePromotionFailure 設置值為不允許,這時就執行 Full GC,或者小于,這時不管HandlePromotionFailure 設置的值是允許還是不允許那么都會執行一次 Full GC 。
如果方法區中內存填滿時也會執行 Full GC ;另外 System.gc() 默認也是觸發 full GC。
七、參考書籍:
《深入理解 Java 虛擬機》周志明 著
總結
以上是生活随笔為你收集整理的Java 虚拟机内存分配与回收策略的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Java 中关于this、static、
- 下一篇: 比较String、StringBuffe
