Tamanho de objects enormes diretamente alocados à geração antiga

Recentemente tenho lido sobre alocações de objects em diferentes gerações em Java. Na maioria das vezes, os novos objects são alocados no Eden (parte da Young Generation) e, depois, são promovidos para Old Generation se algum dos critérios a seguir for atendido.

(1) a idade do object alcançou o limiar de posse
(2) O espaço do sobrevivente (to) está cheio quando objects estão sendo copiados do Éden (ou) outro espaço sobrevivente (de)

Mas há também um caso especial em que os objects são diretamente alocados na Velha Geração, em vez de serem promovidos da geração jovem. Isso acontece quando o object que estamos tentando criar é enorme (possivelmente da ordem de alguns MBs).


Existe alguma maneira de saber o tamanho / limite dos objects enormes / gigantescos? Estou ciente dos critérios de objects gigantescos para o G1 Garbage Collector. Eu só quero saber o limite de tamanho antes ou no Java 6 .

Obrigado pelo seu tempo 🙂

O tamanho máximo de um object que o HotSpot JVM pode alocar na geração jovem é quase tão grande quanto o tamanho do Eden (YoungGen menos dois espaços Survivor).

É assim que a alocação parece:

  1. Use o buffer de alocação local de encadeamento (TLAB), se tlab_top + size <= tlab_end
    Este é o caminho mais rápido. A alocação é apenas o incremento do ponteiro tlab_top .
  2. Se o TLAB estiver quase cheio, crie um novo TLAB no Eden e tente novamente em um novo TLAB.
  3. Se o espaço restante do TLAB não for suficiente, mas ainda for grande para descartar, tente alocar um object diretamente no Eden. A alocação no Eden também é um incremento de ponteiro ( eden_top + size <= eden_end ) usando a operação atômica, uma vez que o Eden é compartilhado entre todos os threads.
  4. Se a alocação no Eden falhar, uma coleta secundária normalmente ocorre.
  5. Se não houver espaço suficiente no Éden mesmo após o Young GC, será feita uma tentativa de alocar diretamente na geração Antiga.

Você pode definir o limite usando o seguinte sinalizador

 XX:PretenureSizeThreshold=size 

seu valor padrão é 0 Eu suponho que, por padrão, se você não configurá-lo, ele não é considerado com valor = 0 , isso significa que, por padrão, não há valor máximo que atua como limite, por padrão, object é promovido apenas com base número de sobrevivência do GC

Versão 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) 

para obter todas as opções de vm (suportadas) você pode executar

 java -XX:+PrintVMOptions -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version 

e, em seguida, você pode se referir ao documento de opção hotspot vm ou à opção particular do google se não estiver listado


 byte[] array = new byte[300*1024*1024]; for(MemoryPoolMXBean memoryPoolMXBean: ManagementFactory.getMemoryPoolMXBeans()){ System.out.println(memoryPoolMXBean.getName()); System.out.println(memoryPoolMXBean.getUsage().getUsed()); } 

saídas:

 $ 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 

Sinalizadores de JVM:

-Xms1G -Xmx1G -Xmn500m -XX: PretenureSizeThreshold = 100000000 -XX: + PrintGCDetails

Ao fixar o tamanho da geração jovem em 500MB, o eden chega a 384MB. Assim, qualquer object maior que 384MB vai diretamente para o OldGen e objects com menos de 384MB são alocados no próprio Éden. Você pode encontrar os usos de geração abaixo

byte [] array = novo byte [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 = novo byte [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** 

Para alocação de 400MB, o uso de eden é de 8%, onde o uso de gens é 76% Para alocação de 300MB, o uso de eden é de 88%, onde o uso de gens é 0% É claro que todos os objects cujo tamanho é maior que eden alocado diretamente na velha geração.

Obrigado apangin & Jigar por suas valiosas percepções 🙂
Eu acho que -XX: PretenureSizeThreshold não é considerado em tudo.