每次young gc的時間润脸,和eden空間的大小是正比關系嗎柬脸?
在進入公司之后,這個問題先后被多次問到毙驯,那young gc的時間到底和哪些因素有關呢倒堕?
來看一段代碼,邏輯很簡單爆价,不斷的分配1M的大小涩馆,直到觸發(fā)YGC。
// -Xmx2g -Xms2g -Xmn500m -XX:+PrintGCDetails
// -XX:+UseConcMarkSweepGC -XX:+PrintHeapAtGC
public class GcCase {
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
allocate_1M();
}
}
public static void allocate_1M() {
byte[] _1M = new byte[1024 * 1000];
}
}
這里設置了新生代的大小是500m允坚,按照8:1:1的比例魂那,eden的大小應該是400m。我們可以大概梳理一下:
1稠项、每次分配1M涯雅,分配到第400次時,eden被1M的內存塊塞滿了
2展运、為了能夠塞下后面的數據的活逆,只能觸發(fā)一次YGC
3、執(zhí)行YGC之前拗胜,必須等所有的業(yè)務線程全部掛起蔗候,這個點就是所謂的安全點(safepoint),從這一刻開始埂软,JVM是凍結的锈遥,只有虛擬機線程才能執(zhí)行,也是從這一刻開始計時勘畔。
一次YGC過程包括下面幾個步驟所灸,每個步驟的耗時,也就是整個YGC的耗時炫七。
1爬立、找出所有可能存活的對象,一個也不能少万哪,這是標記過程的耗時侠驯。
從GC Roots開始抡秆,遍歷對象,所有能遍歷到的對象都是算是存活對象吟策,打上一個標記琅轧。正常情況下,需要的關心的GC Roots包括下面幾個:類的靜態(tài)引用踊挠、業(yè)務線程進入安全點時乍桂,正在執(zhí)行方法中的引用類型變量(包含參數)、部分老年代的對象(持有引用執(zhí)行新生代對象)效床,還有其它不需要太關注的睹酌,比如VM內部的數據結構。
2剩檀、存活對象被標記出來之后憋沿,需要把這些對象從eden區(qū)或者from區(qū),復制到to區(qū)沪猴,這個復制過程的耗時辐啄,和存活對象的大小數量有很大的關系。這是復制過程的耗時运嗜。
3壶辜、如果開啟了GC日志 -XX:+PrintGCDetails
,那么在YGC過程中担租,還會記錄一些數據到日志中砸民,這個日志的寫入過程,也有可能被影響奋救,這段時間也是YGC的耗時岭参。
所以,young gc的時間尝艘,和eden空間的大小是正比關系嗎演侯?
答案是沒有多大關系。