我目前对G1并发标记触发器的理解是,应用程序启动后直到堆占用百分比达到-XX:InitialHeapOccupancyPercent
默认为45%时,我们才开始进行完全疏散。
在触发第一个标记周期后,必须清理堆,最多清理-XX:G1MixedGCCountTarget
,该堆默认为8。
问题是,如果实时数据量预计为整个堆的70%,那么并发标记阶段将不会被重新触发。因此,我编写了一个简单的程序,该程序确实将元素放入HashMap
中,并且从不删除它们:
public class Main {
public static final Map<Long, String> m = new HashMap<>();
public static void main(String args[]) throws Exception {
long elemKey = 0;
while(true){
m.put(elemKey, new String("abc"));
elemKey++;
}
}
}
并以
身份运行java -XX:InitiatingHeapOccupancyPercent=10 -XX:G1HeapRegionSize=4m \
-XX:G1MixedGCCountTarget=32 -Xmx8g -Xlog:gc* Main
在日志中,我发现至少有两个并发标记阶段:
[0,108s][info][gc ] GC(2) Concurrent Cycle
[0,108s][info][gc,marking ] GC(2) Concurrent Clear Claimed Marks
[0,108s][info][gc,marking ] GC(2) Concurrent Clear Claimed Marks 0,006ms
[0,108s][info][gc,marking ] GC(2) Concurrent Scan Root Regions
[0,109s][info][gc,marking ] GC(2) Concurrent Scan Root Regions 1,378ms
[0,109s][info][gc,marking ] GC(2) Concurrent Mark (0,109s)
[0,109s][info][gc,marking ] GC(2) Concurrent Mark From Roots
[0,110s][info][gc,task ] GC(2) Using 2 workers of 2 for marking
和
[0,223s][info][gc ] GC(7) Concurrent Cycle
[0,223s][info][gc,marking ] GC(7) Concurrent Clear Claimed Marks
[0,223s][info][gc,marking ] GC(7) Concurrent Clear Claimed Marks 0,006ms
[0,223s][info][gc,marking ] GC(7) Concurrent Scan Root Regions
[0,229s][info][gc,marking ] GC(7) Concurrent Scan Root Regions 5,577ms
[0,229s][info][gc,marking ] GC(7) Concurrent Mark (0,229s)
[0,229s][info][gc,marking ] GC(7) Concurrent Mark From Roots
[0,229s][info][gc,task ] GC(7) Using 2 workers of 2 for marking
[0,317s][info][gc,marking ] GC(7) Concurrent Mark From Roots 87,688ms
[0,317s][info][gc,marking ] GC(7) Concurrent Preclean
[0,317s][info][gc,marking ] GC(7) Concurrent Preclean 0,089ms
[0,317s][info][gc,marking ] GC(7) Concurrent Mark (0,229s, 0,317s) 87,824ms
[0,321s][info][gc,start ] GC(7) Pause Remark
[0,322s][info][gc,stringtable] GC(7) Cleaned string and symbol table, strings: 4 processed, 0 removed, symbols: 9 processed, 0 removed
[0,322s][info][gc ] GC(7) Pause Remark 332M->320M(760M) 0,902ms
[0,322s][info][gc,cpu ] GC(7) User=0,01s Sys=0,00s Real=0,00s
[0,322s][info][gc,marking ] GC(7) Concurrent Rebuild Remembered Sets
[0,389s][info][gc,marking ] GC(7) Concurrent Rebuild Remembered Sets 66,698ms
[0,389s][info][gc,start ] GC(7) Pause Cleanup
[0,389s][info][gc ] GC(7) Pause Cleanup 352M->352M(760M) 0,074ms
[0,389s][info][gc,cpu ] GC(7) User=0,00s Sys=0,00s Real=0,00s
[0,389s][info][gc,marking ] GC(7) Concurrent Cleanup for Next Mark
[0,391s][info][gc,marking ] GC(7) Concurrent Cleanup for Next Mark 2,118ms
[0,392s][info][gc ] GC(7) Concurrent Cycle 168,305ms
GC(2)
似乎很清楚,初始堆占用率达到了我设置的10%
阈值,但是GC(7)
的触发因素尚不清楚(至少不可能达到堆占用率由于有生命物体的数量不断增长,因此再次达到了10%的阈值)
问题: :有人可以解释一下什么情况触发了GC(7)
并发标记阶段吗?
UPD:我也尝试禁用-XX:-G1UseAdaptiveIHOP
,但这似乎无济于事。