jvm - 堆內存分配

jvm - 內存空間提到了,建立對象的時候,對象是在堆內存中建立的。但堆內存又分爲新生代和老年代,新生代又細分Eden空間、From Survivor空間、To Survivor空間。咱們建立的類到底在哪裏?jvm

對象優先在Eden分配

堆內存分爲新生代和老年代,新生代是用於存放使用後準備被回收的對象,老年代是用於存放生命週期比較長的對象。大部分咱們建立的對象,都屬於生命週期比較短的,因此會存放在新生代。新生代又細分Eden空間、From Survivor空間、To Survivor空間,咱們建立的對象,對象優先在Eden分配。
image.png
隨着對象的建立,Eden剩餘內存空間愈來愈少,就會觸發Minor GC,因而Eden的存活對象會放入From Survivor空間。
image.png
Minor GC後,新對象依然會往Eden分配。
image.png
Eden剩餘內存空間愈來愈少,又會觸發Minor GC,因而Eden和From Survivor的存活對象會放入To Survivor空間。
image.png性能

大對象直接進入老年代

在上面的流程中,若是一個對象很大,一直在Survivor空間複製來複制去,那很費性能,因此這些大對象直接進入老年代。能夠用XX:PretenureSizeThreshold來設置這些大對象的閾值。
image.pngspa

長期存活的對象將進入老年代

在上面的流程中,若是一個對象Hello_A,已經經歷了15次Minor GC還存活在Survivor空間中,那他即將轉移到老年代。這個15能夠經過-XX:MaxTenuringThreshold來設置的,默認是15。虛擬機爲了給對象計算他到底經歷了幾回Minor GC,會給每一個對象定義了一個對象年齡計數器。若是對象在Eden中通過第一次Minor GC後仍然存活,移動到Survivor空間年齡加1,在Survivor區中每經歷過Minor GC後仍然存活年齡再加1。年齡到了15,就到了老年代。
image.pngcode

動態年齡判斷

除了年齡達到MaxTenuringThreshold的值,還有另一個方式進入老年代,那就是動態年齡判斷:在Survivor空間中相同年齡全部對象大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就能夠直接進入老年代。
好比Survivor是100M,Hello1和Hello2都是3歲,且總和超過了50M,Hello3是4歲,這個時候,這三個對象都將到老年代。
image.png對象

空間分配擔保

上面的流程提過,存活的對象都會放入另一個Survivor空間,若是這些存活的對象比Survivor空間還大呢?整個流程以下:blog

  1. Minor GC以前,虛擬機會先檢查老年代最大可用的連續空間是否大於新生代全部對象總空間,若是大於,則發起Minor GC。
  2. 若是小於,則看HandlePromotionFailure有沒有設置,若是沒有設置,就發起full gc。
  3. 若是設置了HandlePromotionFailure,則看老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,若是小於,就發起full gc。
  4. 若是大於,發起Minor GC。Minor GC後,看Survivor空間是否足夠存放存活對象,若是不夠,就放入老年代,若是夠放,就直接存放Survivor空間。若是老年代都不夠放存活對象,擔保失敗(Handle Promotion Failure),發起full gc。

image.png

相關文章
相關標籤/搜索