Here is my simple gc test:
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) {}
}
}
Using these args (G1 enabled):
java -Xmx2G -Xms2G -XX:MaxPermSize=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
-XX:+PrintAdaptiveSizePolicy -Xloggc:jvm.log -XX:+UseG1GC
-XX:InitiatingHeapOccupancyPercent=5 Main
I grep the output:
grep -E "(Full|GC cleanup)" jvm.log
and get something like this:
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]
It seems that soft references were collected during ParallelGc's full collections while concurrent collections were almost useless. Heap dumps from VisualVm also prove this version.
Do I miss something or it is a bug in G1?
Checked on 1.7.0_51-b13 and 1.8.0_45-b15 x64.
Perhaps you are confusing with weak references?
The GC is not forced to collect soft references, unless it finds itself under severe memory pressure.
See here for more information.
In particular, notice the following quote from the documentation:
The only real guarantee the documentation offers is as follows: