1. 程式人生 > >記憶體分配和回收策略簡述

記憶體分配和回收策略簡述

物件優先在Eden分配

大多數情況下,物件在新生代Eden區中分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。

新生代GC(Minor GC):指發生在新生代的垃圾收集動作,因為Java物件大多都具備朝生夕滅的特性,所以Minor GC非常頻繁,一般回收速度也比較快。

老年代GC(Major GC / Full GC):指發生在老年代的GC,出現了Major GC,經常會伴有至少一次的Minor GC(但非絕對的,在Parallel Scavenge收集器的收集策略裡就有直接進行Major GC的策略選擇過程)。Major GC的速度一般會比Minor GC慢10倍以上。

大物件直接進入老年代

所謂的大物件是指,需要大量連續記憶體空間的Java物件,最典型的大物件就是那種很長的字串以及陣列(筆者列出的例子中的byte[]陣列就是典型的大物件)。大物件對虛擬機器的記憶體分配來說就是一個壞訊息(替Java虛擬機器抱怨一句,比遇到一個大物件更加壞的訊息就是遇到一群“朝生夕滅”的“短命大物件”,寫程式的時候應當避免),經常出現大物件容易導致記憶體還有不少空間時就提前觸發垃圾收集以獲取足夠的連續空間來“安置”它們。

虛擬機器提供一個-XX:PretenureSizeThreshold引數,令大於這個設定值的物件直接在老年代分配。這樣做的目的是避免在Eden區及兩個Survivor區之間發生大量的記憶體複製(複習一下:新生代採用複製演算法收集記憶體)。

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

既然虛擬機器採用了分代收集的思想來管理記憶體,那麼記憶體回收時就必須能識別哪些物件應放在新生代,哪些物件應放在老年代中。為了做到這點,虛擬機器給每個物件定義了一個物件年齡(Age)計數器。如果物件在Eden出生並經過第一次Minor GC後仍然存活,並且被Survivor容納的話,將被移動到Survivor空間中,並且物件年齡設為1。物件在Survivor區中每“熬過”一次Minor GC,年齡就增加1歲,當它的年齡增加到一定程度(預設為15歲),就將會被晉升到老年代中。物件晉升老年代的年齡閾值,可以通過引數-XX:MaxTenuringThreshold設定。

動態物件年齡判定

為了能更好地適應不同程式的記憶體狀況,虛擬機器並不是永遠地要求物件的年齡必須達到了MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有物件大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的物件就可以直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。

空間分配擔保

在發生Minor GC之前,虛擬機器會先檢查老年代最大可用的連續空間是否大於新生代所有物件總空間,如果這個條件成立,那麼Minor GC可以確保是安全的。如果不成立,則虛擬機器會檢視HandlePromotionFailure設定值是否允許擔保失敗。如果允許,那麼會繼續檢查老年代最大可用的連續空間是否大於歷次晉升到老年代物件的平均大小,如果大於,將嘗試著進行一次Minor GC,儘管這次Minor GC是有風險的;如果小於,或者HandlePromotionFailure設定不允許冒險,那這時也要改為進行一次Full GC。

下面解釋一下“冒險”是冒了什麼風險,前面提到過,新生代使用複製收集演算法,但為了記憶體利用率,只使用其中一個Survivor空間來作為輪換備份,因此當出現大量物件在Minor GC後仍然存活的情況(最極端的情況就是記憶體回收後新生代中所有物件都存活),就需要老年代進行分配擔保,把Survivor無法容納的物件直接進入老年代。與生活中的貸款擔保類似,老年代要進行這樣的擔保,前提是老年代本身還有容納這些物件的剩餘空間,一共有多少物件會活下來在實際完成記憶體回收之前是無法明確知道的,所以只好取之前每一次回收晉升到老年代物件容量的平均大小值作為經驗值,與老年代的剩餘空間進行比較,決定是否進行Full GC來讓老年代騰出更多空間。

取平均值進行比較其實仍然是一種動態概率的手段,也就是說,如果某次Minor GC存活後的物件突增,遠遠高於平均值的話,依然會導致擔保失敗(Handle Promotion Failure)。如果出現了HandlePromotionFailure失敗,那就只好在失敗後重新發起一次Full GC。雖然擔保失敗時繞的圈子是最大的,但大部分情況下都還是會將HandlePromotionFailure開關開啟,避免Full GC過於頻繁。

在JDK 6 Update 24之後的規則變為只要老年代的連續空間大於新生代物件總大小或者歷次晉升的平均大小就會進行Minor GC,否則將進行Full GC。

相關推薦

記憶體分配回收策略簡述

物件優先在Eden分配 大多數情況下,物件在新生代Eden區中分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。 新生代GC(Minor GC):指發生在新生代的垃圾收集動作,因為Java物件大多都具備朝生夕滅的特性,所以Minor GC非常頻繁

簡述Java記憶體分配回收策略以及Minor GC Major GC(Full GC)

記憶體分配: 1. 棧區:棧可分為Java虛擬機器和本地方法棧 2. 堆區:堆被所有執行緒共享,在虛擬機器啟動時建立,是唯一的

自動記憶體管理機制(4)- 記憶體分配回收策略

自動記憶體管理機制(4)- 記憶體分配和回收策略 Java所承諾的自動記憶體管理主要是針對物件記憶體的回收和物件記憶體的分配。 在Java虛擬機器的五塊記憶體空間中,程式計數器、Java虛擬機器棧、本地方法棧記憶體的分配和回收都具有確定性,一般在編譯階段就能確定需要分配的記憶體大小,

GC發生時記憶體分配回收策略

在《深入理解java虛擬機器》一書中讀到3.6章節,記憶體分配和回收策略: 預備知識 java堆=年輕代(Eden+Survivor+Survivor)+老年代 Eden:Survivor:Survivor預設比例8:1:1,每次年輕代使用率90%(Ede

記憶體分配回收策略

         在發生Minor GC之前,虛擬機器會先檢查老年代最大可用的連續空間是否大於新生代所有物件總空間,如果這個條件成立,那麼Minor GC可以確保是安全的。 如果不成立,則虛擬機器會檢視HandlePromotionFailure設定值是否允許擔保失敗。 如果允許,那麼會繼續檢查老年代最大可

java記憶體分配回收策略

一、導論   java技術體系中所提到的記憶體自動化管理歸根結底就是記憶體的分配與回收兩個問題,之前已經和大家談過java回收的相關知識,今天來和大家聊聊java物件的在記憶體中的分配。通俗的講,物件的記憶體分配就是在堆上的分配,物件主要分配在新生代的Eden上(關於物件在

淺談java內存分配回收策略

內存空間 高效率 cde map details 閾值 老年代 total 關於 一、導論   java技術體系中所提到的內存自動化管理歸根結底就是內存的分配與回收兩個問題,之前已經和大家談過java回收的相關知識,今天來和大家聊聊java對象的在內存中的分配。通俗的講,對

垃圾收集器與記憶體分配策略(六)——記憶體分配回收策略

物件的記憶體分配,往大方向上講,就是在堆上分配(但也可能經過JIT編譯後被拆散為標量型別並間接地棧上分配),物件主要分配在新生代的Eden區上,如果啟動了本地執行緒分配緩衝,將按執行緒優先在TLAB上分配。少數情況下也可能會直接分配在老年代中,分配的規則並不是百分之百固定的,

JAVA虛擬機器(五)垃圾收集器與物件分配回收策略

可達性分析演算法的效率 可達性分析中從GC Roots節點找引用鏈,可作為GC Roots的節點主要在全域性性的引用(常量或類靜態屬性)與執行上下文(棧幀中的本地變量表),如果要逐個檢查,必然會消耗很多時間。 另外,可達性分析對執行時間的敏感還體現在GC停頓上,

最簡單例子圖解JVM記憶體分配回收

一、簡介 JVM採用分代垃圾回收。在JVM的記憶體空間中把堆空間分為年老代和年輕代。將大量(據說是90%以上)建立了沒多久就會消亡的物件儲存在年輕代,而年老代中存放生命週期長久的例項物件。年輕代中又被分為Eden區(聖經中的伊甸園)、和兩個Survivor區。新的物件分配是首先放在Eden區

JVM:GC-記憶體分配回收策略

物件優先在Eden區分配 物件優先在eden區分配,當eden區沒有足夠空間分配記憶體時,就會發現minor gc. 程式碼例項: public class Main { static int _1M = 1024*1024; //vm 引數 // -ver

JVM六:記憶體分配回收策略

對於物件的回收,前面以及講過具體的回收機制,下面我們來看看物件的分配策略! ①物件優先在Eden區域分配 大多數情況下,物件在新生代Eden區分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。 虛擬機器提供了-XX:PrintGCDetails這個收集日誌引數

Java 記憶體分配回收機制

Java的GC機制是自動進行的,和c語言有些區別需要程式設計師自己保證記憶體的使用和回收。 Java的記憶體分配和回收也主要在Java的堆上進行的,Java的堆中儲存了大量的物件例項,所以Java的堆也叫GC堆。 Java在垃圾收集的過程中,主要用到了分代收集演算法,

JVM之記憶體分配回收策略

JVM之記憶體分配與回收策略 來源 https://www.cnblogs.com/xiaoxi/p/6557473.html   JVM分代垃圾回收策略的基礎概念 來源 https://www.cnblogs.com/xiaoxi/p/6602166.html 一、為

java虛擬機器-記憶體分配回收策略

1.物件優先在Eden分配 大多數情況下,物件在新生代Eden區分配。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。 虛擬機器提供了-XX:+PrintGCDetails這個收集器日誌引數,告訴虛擬機器在傳送垃圾收集行為時列印記憶體回收日誌,並且在

Java虛擬機器(三):記憶體分配回收策略

[GC[DefNew Desired survivor size 524288 bytes, new threshold 1 (max 1) - age 1: 748104 bytes, 748104 total : 5024K->730K(9216K), 0.0038710 sec

淺談CLR的記憶體分配回收機制

相對於C++程式設計師來說,C#程式設計師是非常幸運的,至少我們不需要為記憶體洩漏(Memory Leak)而頭疼,不需要負責記憶體的分配和回收。但這不意味著我們只需要知道new的語法就可以了,作為一個嚴肅的C#程式設計師,我們應該對此有所瞭解,有助於我們編寫效能更好的程式碼。 主要內容: CLR的記憶體分

C++ 記憶體分配回收 (new delete)

“new”是C++的一個關鍵字,同時也是操作符。對於new的內容總結。 1、new的過程 當我們使用關鍵字new在堆上動態建立一個物件時,它實際上做了三件事:獲得一塊記憶體空間、呼叫建構函式、返回正確的指標。當然,如果我們建立的是簡單型別的變數,那麼第二步會被省略。假如我們

記憶體分配回收策略(五)

回收策略: Minor GC Major GC/Full GC Minor GC:發生在新生代的GC,發生非常頻繁,消耗時間短。 Major GC:發生在老年代GC,消耗時間一般為新生代GC的10倍,甚至更多(1000倍)。 Full GC:新生代+老年代 GC。

Java虛擬機器原理、記憶體分配回收機制

通常情況下Java編譯過的程式碼是一些class檔案,Java虛擬機器在執行程式碼的時候,首先解析Class,查詢該類的方法、常量,這些對於常規情況下都編譯成二進位制的程式碼儲存在jar檔案中,而對於Java的反射,VM的類載入器需要動態的查詢這些類名,雖然節省了編譯時間,但是執行時的查詢大大降低執行效率。