Подтвердить что ты не робот

Размер огромных объектов, непосредственно выделенных для старого поколения

Недавно я читал о распределении объектов в разных поколениях Java. В большинстве случаев новые объекты выделяются в Eden (часть Young Generation), а затем они продвигаются в Old Generation, если выполняется один из следующих критериев.

(1) Возраст объекта достиг порога владения / (2) Оставшееся место (to) заполнено, когда объекты копируются из Eden (или) другого места для оставшегося в живых (из)

Но есть также особый случай, когда объекты непосредственно выделяются в Старом Поколении вместо того, чтобы продвигаться от молодого поколения. Это происходит, когда объект, который мы пытаемся создать, огромен (возможно, порядка нескольких МБ).


Есть ли способ узнать размер/предел огромных/гигантских объектов? Я знаю о критериях огромных объектов для G1 Garbage Collector. Я просто хочу знать ограничение размера до или в Java 6.

Спасибо за ваше время:)

4b9b3361

Ответ 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 вообще не рассматривается.