Прежде всего, вы указываете -XX:SurvivorRatio=8
, но -XX:+UseAdaptiveSizePolicy
включен, так как SurvivorRatio
просто игнорируется.
Затем я объяснил, какие строки вы видите немного в этом ответе .
В любом случае, я запустил это с java-13
и Unified Logging, в частности с:
"-Xlog:heap*=debug" "-Xlog:gc*=debug"
, чтобы увидеть, что происходит.
Из журналов я вижу, что в этом коде есть только два цикла G C. На самом деле это всего лишь один, параллельный цикл, но как часть этого цикла, также запускается young G C. Логически, я рассматриваю это как один цикл G C, но G C регистрирует отчеты как два.
Таким образом, ваши журналы будут содержать:
[0.127s][debug][gc,ergo] Request concurrent cycle initiation (requested by GC cause). GC cause: G1 Humongous Allocation
И также у вас будет:
[0.133s][info ][gc ] GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation) 7M->6M(20M) 5.753ms
[0.133s][info ][gc,cpu] GC(0) User=0.01s Sys=0.00s Real=0.01s
[0.133s][info ][gc ] GC(1) Concurrent Cycle
Обратите внимание на параллельный цикл спиной к молодому циклу с 1 Young = 1 Eden + 0 Survivors
Позже будет журнал:
[0.133s][info ][gc,heap] GC(0) Eden regions: 1 -> 0 (9)
[0.133s][info ][gc,heap] GC(0) Survivor regions: 0 -> 1 (2)
Как я объяснил в приведенной выше ссылке, следующий цикл молодого Г C намекнут на использование:
11 young regions = 9 Eden + 2 Survivor
Но, как я уже сказал, это только подсказка. Поскольку это огромное распределение , при выходе из него будет фактически использовано меньше областей, как видно из схемы кучи:
[0.157s][info ][gc,heap,exit] garbage-first heap total 20480K....
[0.158s][info ][gc,heap,exit] region size 1024K, 2 young 1 survivors
G C даже не подозревает, что вы выделяете только большие объекты, и он не должен использовать какие-либо молодых регионов вообще, а его эвристика все еще говорит о создании некоторых молодых регионов. Вот почему вы видите эти 2 young, 1 survivor
.
Но, если вы запустите свой код достаточно долго:
public static void main(String[] args) {
while (true) {
invokeMe();
}
}
public static int invokeMe() {
int x = 1024;
int factor = 2;
byte[] allocation1 = new byte[factor * x * x];
allocation1[2] = 3;
byte[] allocation2 = new byte[factor * x * x];
byte[] allocation3 = new byte[factor * x * x];
byte[] allocation4 = new byte[factor * factor * x * x];
return Arrays.hashCode(allocation1) ^ Arrays.hashCode(allocation2)
^ Arrays.hashCode(allocation3) ^ Arrays.hashCode(allocation4);
}
Вы начнете видеть записи вроде:
[0.521s][debug][gc,heap] GC(62) Heap before GC invocations=62
[0.521s][debug][gc,heap] GC(62) region size 1024K, 0 young (0K), 0 survivors (0K)
Обратите внимание на 0 young, 0 survivor
.