Размер огромных объектов, непосредственно выделенных для старого поколения
Недавно я читал о распределении объектов в разных поколениях Java. В большинстве случаев новые объекты выделяются в Eden (часть Young Generation), а затем они продвигаются в Old Generation, если выполняется один из следующих критериев.
(1) Возраст объекта достиг порога владения /
(2) Оставшееся место (to) заполнено, когда объекты копируются из Eden (или) другого места для оставшегося в живых (из)
Но есть также особый случай, когда объекты непосредственно выделяются в Старом Поколении вместо того, чтобы продвигаться от молодого поколения. Это происходит, когда объект, который мы пытаемся создать, огромен (возможно, порядка нескольких МБ).
Есть ли способ узнать размер/предел огромных/гигантских объектов? Я знаю о критериях огромных объектов для G1 Garbage Collector. Я просто хочу знать ограничение размера до или в Java 6.
Спасибо за ваше время:)
Ответы
Ответ 1
Максимальный размер объекта JSM HotSpot, который может выделяться в молодое поколение, почти такой же размер, как размер Eden (YoungGen минус два пространства для выживания).
То, как распределение выглядит грубо:
- Использовать локальный буфер распределения потока (TLAB), если
tlab_top
+ size
<= tlab_end
Это самый быстрый путь. Выделение - это только приращение указателя tlab_top
.
- Если TLAB почти заполнен, создайте новый TLAB в Eden и повторите попытку в новом TLAB.
- Если оставшееся пространство TLAB недостаточно, но оно по-прежнему велико для удаления, попробуйте выделить объект непосредственно в Eden. Выделение в Eden также является приращением указателя (
eden_top
+ size
<= eden_end
) с использованием атомной операции, так как Eden разделяется между всеми потоками.
- Если распределение в Eden не выполняется, обычно возникает небольшая коллекция.
- Если в Eden недостаточно места даже после Young GC, делается попытка выделить непосредственно в старом поколении.
Ответ 2
Вы можете установить предел, используя следующий флаг
XX:PretenureSizeThreshold=size
его значение по умолчанию равно 0
Я предполагаю, что по умолчанию, если вы его не задали, он не рассматривается со значением = 0
, это означает, что по умолчанию не существует максимального значения, которое действует как порог, объект по умолчанию получает повышение только на основании количества выживаемости GC
Версия HotSpot
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
чтобы получить все vm-параметры (поддерживаемые), вы можете запустить
java -XX:+PrintVMOptions -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version
а затем вы можете обратиться к hotspot vm option document или к определенному варианту Google, если не указан
byte[] array = new byte[300*1024*1024];
for(MemoryPoolMXBean memoryPoolMXBean: ManagementFactory.getMemoryPoolMXBeans()){
System.out.println(memoryPoolMXBean.getName());
System.out.println(memoryPoolMXBean.getUsage().getUsed());
}
выходы:
$ java -Xmx1500m -Xms1500m -Xmn500m -XX:PretenureSizeThreshold=100000000 -XX:+PrintGCDetails JVMMemoryInspection
Code Cache
393664
PS Eden Space
330301752
PS Survivor Space
0
PS Old Gen
0
PS Perm Gen
2749520
Ответ 3
Флаги JVM:
-Xms1G -Xmx1G -Xmn500m -XX: PretenureSizeThreshold = 100000000 -XX: + PrintGCDETails
Зафиксировав размер молодого поколения до 500 Мбайт, eden составляет около 384 МБ, поэтому любой объект размером более 384 МБ переходит непосредственно в OldGen, а объект размером менее 384 МБ выделяется в самом Eden. Вы можете найти способы генерации ниже
byte [] array = новый байт [400 * 1024 * 1024];
PSYoungGen total 448000K, used 30720K
eden space 384000K, 8% used
from space 64000K, 0% used
to space 64000K, 0% used
ParOldGen total 536576K, used 409600K
object space 536576K, 76% used
byte [] array = новый байт [300 * 1024 * 1024];
PSYoungGen total 448000K, used 337920K
eden space 384000K, 88% used
from space 64000K, 0% used
to space 64000K, 0% used
ParOldGen total 536576K, used 0K
object space 536576K, **0% used**
При распределении 400 Мбайт использование eden составляет 8%, когда использование старого поколения составляет 76%
При распределении 300 Мбайт использование eden составляет 88%, когда использование старого поколения составляет 0%
Поэтому ясно, что все объекты, размер которых больше, чем eden, будут выделены непосредственно в старый ген.
Спасибо Апангин и Джигар за ваши ценные идеи:)
Я думаю -XX: PretenureSizeThreshold вообще не рассматривается.