Trabajar con generaciones de objetos

Los recolectores de basura de Java implementan una estrategia de recolección de basura generacional que puede clasificar objetos por edad.

Tal necesidad (marcar y compactar todos los objetos) en la JVM puede llamarse ineficiente. Dado que a medida que se asigna una gran cantidad de objetos, su lista crece, lo que conduce a un aumento en el tiempo de recolección de elementos no utilizados. El análisis empírico de las aplicaciones ha demostrado que la mayoría de los objetos en Java son de corta duración.

El área de memoria de pila en la JVM se divide en tres secciones:

Trabajar con generaciones de objetos

Generación más joven

Los objetos recién creados comienzan en la generación más joven. La generación más joven se subdivide en dos categorías.

  • Eden Space : todos los objetos nuevos comienzan aquí, se les asigna memoria inicial.
  • Survivor Spaces (FromSpace y ToSpace): los objetos se mueven aquí desde Eden después de sobrevivir a un ciclo de recolección de basura.

El proceso en el que los objetos se recolectan como basura de la generación más joven se denomina evento de recolección de basura menor.

Cuando el espacio de Eden se llena de objetos, se realiza una pequeña recolección de basura. Todos los objetos muertos se eliminan y todos los vivos se mueven a uno de los dos espacios restantes. El GC pequeño también verifica los objetos en el espacio de supervivientes y los mueve a otro (siguiente) espacio de supervivientes.

Tomemos la siguiente secuencia como ejemplo.

  1. Hay objetos de ambos tipos (vivos y muertos) en el Edén.
  2. Se produce un pequeño GC: todos los objetos muertos se eliminan de Eden. Todos los objetos vivos se mueven al espacio-1 (FromSpace). Eden y space-2 ahora están vacíos.
  3. Se crean y agregan nuevos objetos a Eden. Algunos objetos en Eden y space-1 se vuelven muertos.
  4. Se produce un pequeño GC: todos los objetos muertos se eliminan de Eden y space-1. Todos los objetos vivos se mueven al espacio-2 (ToSpace). Eden y space-1 están vacíos.

Así, en cualquier momento, uno de los espacios de supervivientes siempre está vacío. Cuando los sobrevivientes alcanzan un cierto umbral para moverse a través de los espacios de sobrevivientes, avanzan a una generación anterior.

Puede usar el indicador -Xmn para establecer el tamaño de la generación joven .

Vieja generación

Los objetos que viven una cantidad significativa de tiempo (por ejemplo, la mayor parte de la vida útil de un programa) eventualmente se convierten en objetos más antiguos: centenarios. También se conoce como la generación normal y contiene objetos que se han dejado en Survivor Spaces durante mucho tiempo.

El umbral de vida útil de un objeto determina cuántos ciclos de recolección de elementos no utilizados debe atravesar antes de pasar a la generación anterior. El proceso cuando los objetos se envían a la basura desde la generación anterior se denomina evento principal de recolección de basura.

Puede utilizar los indicadores -Xms y -Xmx para establecer el tamaño de memoria de pila inicial y máximo .

Debido a que Java utiliza la recolección de basura generacional, cuantos más eventos de recolección de basura experimenta un objeto, más se mueve en el montón. Comienza en la generación más joven y eventualmente termina en la generación regular si vive lo suficiente.

Para entender la promoción de objetos entre espacios y generaciones, considere el siguiente ejemplo:

Cuando se crea un objeto, primero se coloca en el espacio Edén de la generación joven.

Tan pronto como se produce una pequeña recolección de basura, los objetos vivos de Eden se trasladan a FromSpace. Cuando ocurre la próxima recolección de basura menor, los objetos vivos tanto de Eden como del espacio se mueven a ToSpace.

Este ciclo continúa un cierto número de veces. Si el objeto todavía está "en servicio" después de este punto, el siguiente ciclo de recolección de elementos no utilizados lo moverá al espacio de una generación más antigua.

Generación permanente y metaespacio

Los metadatos como clases y métodos se almacenan en generación persistente. La JVM lo llena en tiempo de ejecución en función de las clases utilizadas por la aplicación. Las clases que ya no se usan pueden pasar de generación permanente a basura.

Puede usar los indicadores -XX:PermGen y -XX:MaxPermGen para establecer el tamaño inicial y máximo de la generación permanente .

espacio meta

Desde Java 8, el espacio PermGen ha sido reemplazado por el espacio de memoria MetaSpace. La implementación difiere de PermGen: este espacio de almacenamiento dinámico ahora se cambia automáticamente.

Esto evita el problema de falta de memoria de la aplicación que ocurre debido al tamaño limitado del espacio de almacenamiento dinámico de PermGen. La memoria del metaespacio se puede recolectar como basura, y las clases que ya no están en uso se limpiarán automáticamente cuando el metaespacio alcance su tamaño máximo.