Мое текущее понимание триггеров одновременной маркировки 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
В журналах я обнаружил, что вминимум 2 одновременных этапа отметки:
[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
, но, похоже, это не помогает.