Tamaño de objetos enormes asignados directamente a la generación anterior

Recientemente he estado leyendo acerca de las asignaciones de objetos en diferentes generaciones en Java. La mayoría de las veces, los objetos nuevos se asignan en Eden (parte de Young Generation) y luego son promovidos a Old Generation si se cumple alguno de los siguientes criterios.

(1) La edad del objeto alcanzó el umbral de tenencia
(2) El espacio de superviviente (a) está lleno cuando se están copiando objetos del Edén (o) otro espacio de superviviente (desde)

Pero también hay un caso especial en el que los objetos se asignan directamente en la Vieja Generación en lugar de ser promovidos desde la generación joven. Esto sucede cuando el objeto que intentamos crear es enorme (posiblemente del orden de pocos MB).


¿Hay alguna manera de saber el tamaño / límite de los objetos grandes / enormes? Estoy al tanto de los enormes criterios de los objetos para G1 Garbage Collector. Solo quiero saber el límite de tamaño antes o en Java 6 .

Gracias por tu tiempo 🙂

    El tamaño máximo de un objeto que HotSpot JVM puede asignar en la generación joven es casi tan grande como el tamaño del Edén (YoungGen menos dos espacios de Superviviente).

    Así es como se ve la asignación de forma ruda:

    1. Utilice el búfer de asignación local de subprocesos (TLAB), si tlab_top + size < = tlab_end
      Este es el camino más rápido. La asignación es solo el incremento del puntero tlab_top .
    2. Si TLAB está casi lleno, cree un TLAB nuevo en Eden y vuelva a intentarlo en un TLAB nuevo.
    3. Si el espacio restante de TLAB no es suficiente pero aún es demasiado grande para descartar, trate de asignar un objeto directamente en Eden. La asignación en Eden también es un incremento de puntero ( eden_top + size < = eden_end ) usando la operación atómica, ya que Eden se comparte entre todos los hilos.
    4. Si la asignación en Eden falla, generalmente ocurre una recolección menor.
    5. Si no hay suficiente espacio en Eden incluso después de Young GC, se hace un bash de asignar directamente en la generación anterior.

    Puedes establecer el límite usando la siguiente bandera

     XX:PretenureSizeThreshold=size 

    su valor predeterminado es 0 Supongo que, de manera predeterminada, si no lo establece, no se considera con value = 0 , lo que significa que no existe un valor máximo que actúe como umbral, por defecto el objeto se promociona solo en función de cantidad de supervivencia de GC

    Versión de 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 obtener todas las opciones de vm (compatibles) puede ejecutar

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

    y luego puede consultar el documento de opción hotspot vm o la opción google particular si no figura en la lista


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

    productos:

     $ 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 

    Banderas de JVM:

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

    Al fijar el tamaño de la generación joven a 500MB, eden llega a alrededor de 384MB, por lo que cualquier objeto mayor de 384MB va directamente a OldGen y se asigna menos de 384MB en Eden. Puede encontrar los usos de generación a continuación

    byte [] matriz = nuevo 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 [] matriz = nuevo 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 una asignación de 400MB, el uso de eden es 8% donde el uso de la vieja generación es 76%. Para una asignación de 300MB, el uso de eden es 88% donde el uso de la vieja generación es 0%. Es claro que todos los objetos cuyo tamaño es mayor que el eden serán asignado directamente en la vieja generación.

    Gracias apangin y Jigar por sus valiosos conocimientos 🙂
    Creo que -XX: PretenureSizeThreshold no se considera en absoluto.