每次young gc的時間,和eden空間的大小是正比關系嗎?
在進入公司之後,這個問題先後被多次問到,那young gc的時間到底和哪些因素有關呢?
來看一段代碼,邏輯很簡單,不斷的配置設定1M的大小,直到觸發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、為了能夠塞下後面的資料的,隻能觸發一次YGC
3、執行YGC之前,必須等所有的業務線程全部挂起,這個點就是所謂的安全點(safepoint),從這一刻開始,JVM是當機的,隻有虛拟機線程才能執行,也是從這一刻開始計時。
一次YGC過程大概包括下面幾個步驟,每個步驟的耗時之和,也就是整個YGC的耗時。
1、找出所有可能存活的對象,一個也不能少,這是标記過程的耗時。
從GC Roots開始,周遊對象,所有能周遊到的對象都是算是存活對象,打上一個标記。正常情況下,需要的關心的GC Roots包括下面幾個:類的靜态引用、業務線程進入安全點時,正在執行方法中的引用類型變量(包含參數)、部分老年代的對象(持有引用執行新生代對象),還有其它不需要太關注的,比如VM内部的資料結構。
2、存活對象被标記出來之後,需要把這些對象從eden區或者from區,複制到to區,這個複制過程的耗時,和存活對象的大小數量有很大的關系。這是複制過程的耗時。
3、如果開啟了GC日志-XX:+PrintGCDetails,那麼在YGC過程中,還會記錄一些資料到日志中,這個日志的寫入過程,也有可能被影響,這段時間也算YGC的耗時。
是以,young gc的時間,和eden空間的大小是正比關系嗎?
答案是沒有多大關系。
歡迎工作一到五年的Java工程師朋友們加入Java架構開發:744677563
本群提供免費的學習指導 架構資料 以及免費的解答
不懂得問題都可以在本群提出來 之後還會有職業生涯規劃以及面試指導