我有這樣的程序:直接分配,以老一代
public static void main(String[] args) {
int sum = 0;
LinkedList<Integer> ll = new LinkedList<>();
for(int i=0;i<Long.MAX_VALUE;i++) {
sum += i;
if (sum % 3 == 0){
ll.add(i);
if (ll.size() % 1000 == 0)
System.out.println("Linked List size: " + ll.size());
}
}
}`
我希望看到什麼是年輕一代正在創建整數對象,他們中的一些添加到鏈表移動到老一代。所以我預計年輕一代GC會隨着物體移動到倖存空間,然後從那裏傳到老一代而持續發生。但是我發現,這是一直在發生的老一代GC,並且根本沒有發生年輕一代GC。這是JVM正在做的某種優化嗎?老一代直接創造物體的地方在哪裏?正如你在下面的圖片中看到的,年輕的gc只發生過兩次,而老gc發生了41次。 Old Generation GC only
接下來,我嘗試了相同的代碼,只是不是將整數對象添加到鏈表中,而是創建了一個新的Object(),令我驚訝的是沒有年輕人或老年人gc。
public static void main(String[] args) {
int sum = 0;
LinkedList<Integer> ll = new LinkedList<>();
for(int i=0;i<Long.MAX_VALUE;i++) {
sum += i;
Object obj = new Object();
}
}
然後,我創建的隨機字符串對象:
public static void main(String[] args) {
int sum = 0;
LinkedList<Integer> ll = new LinkedList<>();
for(int i=0;i<Long.MAX_VALUE;i++) {
sum += i;
String s = String.valueOf(Math.random());
}
}
現在我看到的物體famililar拉鋸格局被轉移到生存空間:
5.833:[GC(分配失敗)[PSYoungGen:1048576K-> 1984K(1223168K)] 1048576K-> 2000K(4019712K),0.0035789s [GC(Allocation Failure)[PSYoungGen:1050560K-> 2000K(1223168K)] 1050576K-> 2024K(4019712K),0.0023286secs] [ecs] [Times:user = 0.01sys = 0.00,real = 0.00sec] 12.678 [GC(分配失敗)[PSYoungGen:1050576K-> 1968K(1223168K)] 1050600K-> 2000K(4019712K),0.0016530秒] [時間:用戶= 0.01 sys = 0.00,實際= 0.00秒] [ [GC(分配失敗)[PSYoungGen:1050544K-> 2000K(1223168K)] 1050576K-> 2040K(4019712K),0.0016131秒] [時間:用戶= 0.01秒] = 0.00,實際= 0.00秒] 24.346 [GC(分配失敗)[PSYoungGen:1050576K-> 1952K(1223168K)] 1050616K-> 2000K(4019712K),0.0018461秒] [Times:user = 0.01 sys = 0.00] ,實際= 0.00秒] 38.519:[GC(分配失敗)[PSYoungGen:1050528K-> 1984K(1395712K)] 1050576K-> 2040K(4192256K),0.0022490secs] [Times:user = 0.01 sys = 0.00,real = 0.00sec] 47.998: [GC(分配失敗)[PSYoungGen:1395648K-> 256K(1394176K)] 1395704K-> 2153K(4190720K),0.0024607秒] [時間:用戶= 0.01 SYS = 0.00,真= 0.00秒]
所以我的問題是GC足夠聰明,可以看到創建的對象在任何地方都沒有被使用並丟棄它們?爲什麼不用字符串?
所以我的問題是爲什麼Integer對象不是在我的第一個例子中在年輕一代中創建的。我期望在年輕一代中創建整數,然後將對該變量的引用添加到列表中,並且年輕一代的掃描將這些對象移動到舊的狀態。 –
您正在得出錯誤的結論。如上所述,舊的gen *集合*並不意味着在舊空間中創建了這些對象。這隻意味着舊一代已經在gc期間被處理,或者是因爲它已被修改,或者因爲整個當前分配的內存已滿。實際上,你的Eden空間包含一個巨大的** 1GB **對象,因此聲稱該對象是在舊世代空間中創建的真的很奇怪。 – Holger
看來你的'-Xms'設置非常高。我建議降低(或刪除)該設置,並在程序開始處插入延遲,然後觀察程序在*整個內存耗盡之前的行爲*。 – Holger