Clasificación de algunos puntos de conocimiento de JVM causados por el algoritmo de reciclaje y la condición de activación y GC (falla de asignación)

Revisé el registro de un programa determinado hace unos días y descubrí que se informó información relacionada con GC. No estoy seguro de si dicha información es correcta o incorrecta, así que aproveché esta oportunidad para revisar el contenido relacionado con GC:

Tome uno de los ejemplos de comportamiento para interpretar la información del registro:

[GC (error de asignación) [ParNew: 367523K-> 1293K (410432K), 0.0023988 segundos] 522739K-> 156516K (1322496K), 0.0025301 segundos] [Tiempos: usuario = 0.04 sys = 0.00, real = 0.01 segundos]

GC :

Indica que se ha realizado una recolección de basura. No hay una modificación completa al frente, lo que indica que este es un GC menor. Tenga en cuenta que no significa que solo la generación joven es GC , y las existentes serán STW independientemente de si es el joven o el viejo .

Error de asignación :

Muestra que la razón de este GC es que no hay suficiente espacio en la generación joven para almacenar nuevos datos.

ParNew :

Indica que este GC ocurrió en la generación joven y se utilizó el recolector de basura ParNew . ParNew es una versión multiproceso del recolector serial que usa múltiples CPU y subprocesos para completar la recolección de basura ( el número de subprocesos usados ​​por defecto es el mismo que el número de CPU , y puede usar el límite del parámetro -XX: ParallelGCThreads) . El recopilador utiliza un algoritmo de copia para recuperar memoria, durante el cual detendrá otros subprocesos de trabajo, a saber, Stop The World.

367523K-> 1293K (410432K) : la unidad es KB

Los tres parámetros son: la capacidad utilizada del área de memoria (en este caso, la generación joven) antes de GC, la capacidad utilizada del área de memoria después de GC y la capacidad total del área de memoria.

0.0023988 segundos :

Tiempo de GC empleado en esta área de memoria, en segundos

522739K-> 156516K (1322496K)

Tres parámetros son: el tamaño del área del montón antes de la recolección de basura, el tamaño del montón de recolección de basura del área, el tamaño del jefe del montón.

0.0025301 segundos :

El tiempo de GC del dominio del área de memoria (aquí está todo el montón) , en segundos

[Tiempos: usuario = 0.04 sys = 0.00, real = 0.01 segundos]

 Representar respectivamente el modo de usuario que consume mucho tiempo, el modo de kernel consume mucho tiempo y el tiempo total

El análisis puede sacar conclusiones:

    La nueva generación de GC se redujo en 367523-1293 = 366239K

    Se ha reducido un total de 522739-156516 = 366223K en el área Heap

366239 - 366223 = 16K, lo que significa que se movió un total de 16K de memoria de la generación joven a la generación anterior. Se puede ver que el número no es grande, lo que indica que todos son objetos con un ciclo de vida corto, pero hay hay muchos de esos objetos.

  Lo que necesitamos es evitar la ocurrencia de Full GC tanto como sea posible, para que los objetos se recolecten en la generación joven tanto como sea posible , por lo que aquí podemos aumentar ligeramente el tamaño de la generación joven, de modo que los datos de 17K sean también almacenado en la generación joven.

Tiempo de GC , con el que se determina el objeto qué método de recuperación se requiere :

  1. Método de recuento de referencia (ya no se usa)
  2. Análisis de accesibilidad

En resumen, lo primero es agregar un contador de referencia al objeto, este contador es +1 cuando hay otras referencias, -1 cuando la referencia no es válida y se puede borrar cuando es 0. Pero no puede resolver el problema de las referencias circulares, por lo que generalmente se usa este último algoritmo.

La idea básica del método de análisis de accesibilidad es utilizar una serie de objetos denominados GC Roots como punto de partida, comenzando desde estos nodos y buscando hacia abajo. La ruta recorrida por la búsqueda se llama Cadena de Referencia. Cuando un objeto alcanza el GC Cuando Roots no está conectado por ninguna cadena de referencia, se demuestra que el objeto es inutilizable y se puede reciclar.

Las raíces de GC son generalmente referencias desde fuera del montón hasta dentro del montón , por ejemplo:

  1. Objetos referenciados en la pila de JVM
  2. Objetos referenciados por propiedades estáticas en el área de métodos
  3. Objetos referenciados por constantes en el área de método
  4. Objetos referenciados en la pila de métodos local 

 

Tome CMS como ejemplo para agregar algunos puntos de conocimiento:

Introducción al algoritmo de replicación:

Debido a que el ciclo de vida de los objetos de nueva generación es generalmente muy corto, el área de memoria generalmente se divide en tres partes, una grande se llama Edén y dos pequeñas se llama Superviviente. La relación entre ellos es generalmente de 8: 1: 1.

Solo usa Eden + una pieza de Survivor cuando lo uses. Cuando el área del Edén esté llena, se realizará un gc menor y los objetos debajo de la supervivencia se copiarán a otro Superviviente . Si no se puede dejar otra parte de Survivor (el parámetro de máquina virtual correspondiente es XX: TargetSurvivorRatio, el valor predeterminado es 50, que es 50%) , maxThresholdAge se actualiza de 15 al objeto actual e incrementa el valor de edad del objeto en el mismo tiempo, y el objeto entra directamente en la vejez.

(Cuando se usa CMS, el colector de nueva generación predeterminado es ParNew) (A veces, cuando el GC de nueva generación necesita encontrar los objetos de nueva generación a los que se hace referencia en la generación anterior, se utilizará una técnica llamada "tabla de cartas" en este momento para evitar la generación. No sé cómo escanear toda la tabla por el momento ..., se presenta la tabla de cartas: https://blog.csdn.net/z69183787/article/details/104939205 )

El significado del área de Superviviente :

Si no hay ningún superviviente, cada vez que Eden realice un gc menor, los objetos supervivientes entrarán en la vejez, y la vejez pronto se completará y entrará en el gc mayor. Dado que el espacio en la vejez es generalmente grande, ¡lleva mucho más tiempo realizar un gc! En particular, la GC completa frecuente afectará la respuesta y la conexión del programa.

Survivor existe para reducir los objetos enviados a la generación anterior, reduciendo así la ocurrencia de Full gc. La configuración predeterminada es que después de 16 veces, el gc menor todavía está vivo en la generación joven antes de que los objetos se envíen a la generación anterior.

Por qué hay dos supervivientes:

 Principalmente para solucionar el problema de la fragmentación y la eficiencia de la memoria . Si solo hay un Superviviente, habrá datos de Eden a Survivor cada vez que se active un GC menor y el ciclo continúa. Tenga en cuenta que el área de Survivor también será recolectada como basura, lo que provocará la fragmentación de la memoria. Como se muestra abajo:

    La fragmentación puede conducir a un espacio contiguo insuficiente en el montón para almacenar un objeto grande, lo que afecta el rendimiento del programa. Si hay dos Supervivientes, los objetos restantes se pueden concentrar en un Superviviente para evitar la fragmentación. Como se muestra abajo:

La diferencia entre GC menor y GC completo y condiciones de activación:

GC menor:

  Para el algoritmo de replicación , cuando el área del Edén de la generación joven esté llena, se activará un GC menor para copiar los objetos supervivientes de Edén y De superviviente a otra pieza de Para superviviente.

    Nota: Si un objeto sobrevive durante más de un cierto número de Minor gc veces, entrará directamente en la vejez y ya no se asignará a To Survivor (predeterminado 15 veces, correspondiente al parámetro de máquina virtual -XX: + MaxTenuringThreshold) .

GC completo:

Se usa para limpiar todo el espacio del montón. Sus condiciones de activación son principalmente las siguientes:

  1. Llame explícitamente al método System.gc (se recomienda que se active JVM).
  2. Espacio insuficiente en el área del método (esto no sucederá en JDK8 y versiones posteriores, consulte los detalles a continuación)
  3. El espacio insuficiente en la generación anterior provocó Full GC. Esta situación es más complicada, existen las siguientes:
    1. Causado por objetos grandes que entran directamente en la vejez, definido por el parámetro -XX: PretenureSizeThreshold
    2. En Minor GC, los objetos que han experimentado múltiples Minor GC y todavía existen entran en la vejez. Como se mencionó anteriormente, está definido por el parámetro -XX: MaxTenuringThreashold
    3. En Minor GC, el mecanismo dinámico de determinación de la edad del objeto transferirá el objeto a la vejez por adelantado. La edad se acumula de joven a viejo. Cuando se agrega un determinado grupo de edad, la suma acumulada excede el área de supervivientes * -XX: TargetSurvivorRatio, los objetos de este grupo de edad hasta la vejez
    4.  En Minor GC, cuando las áreas Eden y From Space se copian en el área To Space, si la memoria es más grande que la memoria disponible en el área To Space, el objeto se transferirá directamente a la generación anterior.

El mecanismo de garantía de asignación de espacio de JVM puede activar la GC completa:

Antes del Minor GC, el mecanismo de asignación de garantía de espacio de JVM puede activar 3.2, 3.3 y 3.4, es decir, activar un GC completo.

La asignación de garantía de espacio significa que antes de que ocurra Minor GC, la máquina virtual verifica si el mayor espacio continuo disponible en la generación anterior es mayor que el espacio total de todos los objetos en la nueva generación.

Si es mayor que, este Minor GC es seguro.

Si es menor, la máquina virtual verifica si el valor de configuración de HandlePromotionFailure permite la falla de garantía. Si HandlePromotionFailure = true, continuará verificando si el espacio continuo máximo disponible en la generación anterior es mayor que el tamaño promedio de los objetos promocionados a la generación anterior. Si es mayor que el tamaño promedio de los objetos promocionados a la generación anterior. generación anterior, se intenta un GC menor, pero esta vez el GC menor sigue siendo riesgoso y falla.Después de eso, se iniciará nuevamente el GC completo; si es menor que o HandlePromotionFailure = false, se realizará el GC completo directamente en su lugar.

Todos dirán que es probable que un GC menor active un GC completo .

PD: ¿Por qué HotSpot cancela la generación permanente en JDK8?

 JDK8 canceló la generación permanente y agregó una nueva área llamada Metaspace, que corresponde al área de método en la especificación de JVM (principalmente almacena información de clase y metadatos). La diferencia es que el metaespacio no usa memoria en la JVM, pero usa memoria local.

Las razones de esto son aproximadamente las siguientes:

       1. Las cadenas existen en la generación permanente, que es propensa a problemas de rendimiento y desbordamiento de memoria.

  2. Es difícil determinar el tamaño de la clase y la información del método, por lo que es más difícil especificar el tamaño de la generación permanente. Demasiado pequeño es propenso al desbordamiento permanente de la generación, y demasiado grande probablemente cause el desbordamiento de la generación anterior. Generacion.

  3. La generación permanente traerá una complejidad innecesaria al GC y la eficiencia de recuperación es baja.

  4. Oracle puede combinar HotSpot y JRockit en uno.

Complemente el diagrama del modelo de memoria JDK8:

 

referencia:

 

https://blog.csdn.net/antony9118/article/details/51425581 (el significado de dos supervivientes)

https://zhidao.baidu.com/question/1111800566588999699.html (Cuándo se activa la GC completa)

https://blog.csdn.net/l1394049664/article/details/81486470#%E4%BA%94%E3%80%81java8%E5%86%85%E5%AD%98%E6%A8%A1%E5 % 9E% 8B% E5% 9B% BE (diagrama del modelo de memoria JDK8)

https://blog.csdn.net/quinnnorris/article/details/75040538 (Análisis del algoritmo de análisis de accesibilidad)

https://segmentfault.com/a/1190000007726689 (cuál es la mesa de cartas)

Supongo que te gusta

Origin blog.csdn.net/z69183787/article/details/104938075
Recomendado
Clasificación