2015-06-10 23 views
3

這裏是我的簡單的GC測試:G1不處理軟引用

public class Main { 

    static class Data { 
    public long[] l = new long[100]; 
    } 

    static List<SoftReference<Data>> list = new ArrayList<>(); 

    public static void main(String[] args) { 
    long i = 0; 

    while (true) { 
     list.add(new SoftReference<>(new Data())); 
     ++i; 
     if (i % 1000 == 0) { 
     sleep(1); 
     if (i % 1_000_000 == 0) 
      sleep(1000); 
     } 
    } 
    } 

    static void sleep(long millis) { 
    try { Thread.sleep(millis); } catch (InterruptedException ignored) {} 
    } 
} 

使用這些ARGS(啓用G1):

java -Xmx2G -Xms2G -XX:MaxPermSize=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
-XX:+PrintAdaptiveSizePolicy -Xloggc:jvm.log -XX:+UseG1GC 
-XX:InitiatingHeapOccupancyPercent=5 Main 

我用grep輸出:

grep -E "(Full|GC cleanup)" jvm.log 

並得到像這樣的東西:

0.564: [GC cleanup 277M->277M(2048M), 0.0009922 secs] 
0.879: [GC cleanup 443M->442M(2048M), 0.0009396 secs] 
1.676: [GC cleanup 859M->856M(2048M), 0.0008681 secs] 
3.530: [GC cleanup 1324M->1320M(2048M), 0.0012422 secs] 
4.838: [GC cleanup 1711M->1707M(2048M), 0.0010601 secs] 
6.334: [Full GC 2047M->102M(2048M), 1.2659685 secs] 
8.322: [GC cleanup 534M->534M(2048M), 0.0009528 secs] 
11.250: [GC cleanup 1460M->1450M(2048M), 0.0011207 secs] 
13.499: [Full GC 2046M->512M(2048M), 1.3534848 secs] 

似乎在ParallelGc的完整集合中收集了軟引用,而併發集合幾乎沒用。從VisualVm堆轉儲也證明了這個版本。

我錯過了什麼,或者它是G1中的錯誤?

檢查1.7.0_51-b13和1.8.0_45-b15 x64。

+0

軟引用將表現得非常奇怪和不確定。強迫GC對他們做任何事情都很難或不可能。 –

+0

看來這個問題已經存在於Oracle bugtracker中,它不會很快關閉:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6912889 –

回答

3

也許你對弱引用感到困惑?

GC不會強制收集軟引用,除非它發現自己處於嚴重的內存壓力下。

有關更多信息,請參見here

具體地說,從文檔注意到以下引用:

軟引用對象,它們在垃圾收集器的響應於存儲器需求清除。

唯一真正保證文檔提供如下:以軟可到達對象都

所有軟引用虛擬機拋出一個OutOfMemoryError之前已經被清除。

+0

謝謝,這聽起來很合理。 –

1

存在控制軟引用收集速率的-XX:SoftRefLRUPolicyMSPerMB=(默認值= 1000)。數值越低,收集速度越快。

我不知道它如何與G1的區域相互作用。有可能某些地區很少被觸及,因此他們的軟參考不會被考慮在內。

由於@sstan提到WeakReferences可能會提供更多的可預測的行爲,但犧牲了引用的更短的生命週期。


另一個問題是,您不清除清空softreference對象的列表。如果您使用reference queue註冊參考號,請在睡眠(1000)之後輪詢該隊列以查找參考,並將它們從列表中刪除,則不應耗盡內存。 爲了更快的查找,一組可能比列表更合適。

+0

不幸的是,SoftRefLRUPolicyMSPerMB無助於擺脫完整的gcs –

+0

更新了我的答案 – the8472