1. 程式人生 > >JVM 記憶體分配與回收策略

JVM 記憶體分配與回收策略

Java 中,物件的記憶體分配,大的方向講,就是在堆上分配。物件主要分配在新生代的eden區上。

記憶體分配規則:

大多數情況,記憶體在新生代eden區中分配,當eden區沒有足夠空間進行分配的時候,虛擬機器將發起一次minor GC

大物件直接進入老年代:

首先需要知道什麼是大物件:

大物件: 需要大量連續記憶體空間的JAVA 物件 ,典型的大物件就是那種很長的字串以及陣列。 大物件對於虛擬機器的記憶體分配來說是個很壞的訊息,經常出現大物件容易導致記憶體中還有不少空間的時候就需要提前觸發垃圾回收來獲取更多的連續空間
虛擬機器提供了一個 -XX:PretenureSizeThreshold 引數,大於這個設定值的物件直接在老年代中進行記憶體分配, 這樣做的母的在於避免新生代發生大量的記憶體複製

長期存活的物件進入老年代:

虛擬機器給每一個物件定義了一個物件年齡計數器。如果物件在Eden 區出生,經過第一次新生代GC 仍然存在,並且能夠被Survivor 容納的,那麼將會移動到Survivor 空間,並且物件年齡設定為1 ,對於Survivor 區中的物件,只要每進過一次新生代GC ,物件年齡就增長一歲,當物件年齡到達晉升老年代的閾值(可以自己設定) 那麼物件就會被晉升到老年代。

動態物件的年齡判定:

為了更好的適應不同程式的記憶體情況,虛擬機器並不是永遠的要求年齡必須達到閾值才能晉升為老年代,虛擬機器會根據survivor裡面相同年齡的所有物件大小的綜合大於survivor大小的一半,年齡大於或等於該年齡的物件就可以直接進入老年代

空間分配擔保:

在發生新生代GC 的時候,虛擬機器會區檢查老年代的連續空間大小是否大於新生代所有物件總空間,如果成立,那麼就可以確定新生代GC 行為是安全的,但是如果小於,那麼就需要檢視是否允許擔保失敗,如果允許,繼續檢查新生代需要晉升的物件的大小是否小於老年代的可用連續空見,如果大於,嘗試進行新生代GC ,如果小於或者不允許進行擔保失敗,那麼新生代GC 就會變成老年代 GC

總結:

記憶體回收和來及收集器很多時候都是影響系統性能,併發能力的主要因素之一,只有根據實際應用需求,實現方式選擇最優的蒐集方式才能獲取最高的效能。在實際的虛擬機器調優階段,必須瞭解具體收集器的行為,優勢和劣勢,以及調節引數,根據程式的實際情況進行調優