El proceso básico y los algoritmos comunes de la recolección de basura de Java.

Tabla de contenido

1. Descripción básica

2. Clasificación de basura

antecedentes basicos

Dé ejemplos para ilustrar el papel de varios tipos de referencia.

Referencia fuerte

Referencia suave

Referencia débil

Referencia fantasma

3. Búsqueda de basura

Encuentra oportunidades basura

Buscar operaciones de spam

4. Limpieza de basura

Introducción a los algoritmos de uso común.

Marcar-barrer

Marcar-copiar

Mark-Compacto

Algoritmo de recopilación generacional

Antecedentes del problema

Descripción del área generacional

Proceso de ejecución del algoritmo de recolección de basura generacional.

Referencias, libros y enlaces.


1. Descripción básica

Cuando se ejecuta un programa Java, los objetos se asignan dinámicamente en la memoria del montón. A medida que se ejecuta el programa, es posible que ya no se haga referencia a algunos objetos y se conviertan en basura. La recolección de basura se refiere a la limpieza de estos objetos basura cuando el programa se está ejecutando para liberar espacio en la memoria para nuevos objetos.

El proceso básico de recolección de basura de Java se puede dividir en los siguientes tres pasos:

  1. Clasificación de basura : el recolector de basura primero debe determinar qué objetos son objetos basura y qué objetos son objetos vivos. Generalmente, el recolector de basura atravesará el gráfico de objetos comenzando desde el nodo raíz del montón (como el contador del programa, la pila de la máquina virtual, la pila de métodos locales y los atributos estáticos de clase en el área del método, etc.) y marcará todos los objetos accesibles como objetos vivos Los objetos sin marcar se consideran objetos basura.
  2. Seguimiento de basura : el recolector de basura necesita encontrar todos los objetos de basura para poder limpiarlos. Diferentes métodos de búsqueda de basura conducirán a diferentes algoritmos de recolección de basura. Los algoritmos comunes de búsqueda de basura incluyen el algoritmo de barrido de marcas, el algoritmo de copia, el algoritmo de clasificación de marcas, el algoritmo generacional, etc.
  3. Recolección de basura : el recolector de basura necesita limpiar todos los objetos de basura. Los métodos de limpieza de basura también son diferentes: los más comunes incluyen el algoritmo de barrido de marcas, el algoritmo de copia, el algoritmo de clasificación de marcas, el algoritmo generacional, etc. La limpieza de basura puede causar pausas en la aplicación. Los diferentes recolectores de basura reducen este tiempo de pausa de diferentes maneras, mejorando así el rendimiento y la confiabilidad de la aplicación.

Cabe señalar que diferentes recolectores de basura pueden usar diferentes algoritmos y estrategias al realizar la recolección de basura, por lo que para diferentes escenarios de aplicación, es necesario seleccionar un recolector de basura apropiado y realizar el ajuste de parámetros apropiado para lograr el mejor efecto de recolección de basura.

2. Clasificación de basura

antecedentes basicos

La clasificación de basura se refiere al proceso de dividir los objetos en el montón en objetos vivos y objetos basura, y no tiene relación directa con tipos de referencia como referencias fuertes, referencias suaves, referencias débiles y referencias virtuales.

En la fase de clasificación de basura, la JVM comenzará desde un conjunto de objetos raíz, atravesará todos los objetos a través de las relaciones de referencia entre objetos y marcará todos los objetos supervivientes. Durante el proceso de marcado, los objetos se marcan para su procesamiento en etapas posteriores de recolección de basura. Los objetos marcados son objetos vivos, mientras que los objetos no marcados se consideran objetos basura y el recolector de basura puede reciclarlos.

Los tipos de referencia, como referencias fuertes, referencias suaves, referencias débiles y referencias virtuales, se utilizan para controlar el ciclo de vida de los objetos durante el proceso de recolección de basura. Su función es decirle al recolector de basura qué objetos se pueden reciclar y cuáles no.

Dé ejemplos para ilustrar el papel de varios tipos de referencia.

Referencia fuerte

La referencia fuerte es el tipo de referencia más común y el tipo de referencia predeterminado. Si un objeto tiene una referencia fuerte, el recolector de basura no lo reclamará. Cuando no hay suficiente espacio de memoria, la JVM prefiere generar un OutOfMemoryError que recuperar objetos con referencias sólidas. Código de ejemplo para referencias sólidas:

Object obj = new Object(); //强引用

Referencia suave

Las referencias suaves se utilizan para describir objetos que son útiles pero no necesarios. Los objetos asociados con referencias suaves solo se reciclarán cuando no haya memoria suficiente. Las referencias suaves se pueden utilizar para implementar cachés sensibles a la memoria, como caché de páginas web, caché de imágenes, etc. Código de ejemplo para referencias suaves:

Object obj = new Object();

SoftReference<Object> softRef = new SoftReference<>(obj); //软引用

obj = null; //obj 不再具有强引用,但仍有软引用

Referencia débil

Las referencias débiles se utilizan para describir objetos no esenciales. Los objetos asociados con referencias débiles solo pueden sobrevivir hasta que se produzca la siguiente recolección de basura. Cuando el recolector de basura está funcionando, los objetos asociados solo con referencias débiles se reciclarán independientemente de si la memoria actual es suficiente. Código de ejemplo para referencias débiles:

Object obj = new Object();

WeakReference<Object> weakRef = new WeakReference<>(obj); //弱引用

obj = null; //obj 不再具有强引用,只有弱引用

Referencia fantasma

Las referencias virtuales, también llamadas referencias fantasma o referencias fantasma, son el tipo de referencia más débil. El recolector de basura puede reciclar un objeto que contiene una referencia virtual en cualquier momento, al igual que si no tuviera ninguna referencia. Las referencias virtuales se utilizan principalmente para rastrear el estado de los objetos que se recolectan como basura. Cuando un objeto está a punto de reciclarse, las referencias virtuales se colocarán en una ReferenceQueue y se pueden obtener notificaciones a través de ReferenceQueue. Código de ejemplo para referencias virtuales:

Object obj = new Object();

ReferenceQueue<Object> queue = new ReferenceQueue<>();

PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue); //虚引用

obj = null; //obj 不再具有强引用,只有虚引用

En resumen, a través de diferentes tipos de referencia, podemos controlar de manera más flexible el ciclo de vida de los objetos y evitar que el recolector de basura los recicle demasiado pronto o demasiado tarde. 

3. Búsqueda de basura

Encuentra oportunidades basura

Diferentes recolectores de basura tienen diferentes estrategias, los siguientes son solo ejemplos:

  • Se solicita espacio insuficiente al solicitar un nuevo espacio para objetos y cargar una clase.
  • El uso de espacio de la generación anterior y la generación permanente ha alcanzado el valor configurado (cms: CMSInitiatingOccupancyFraction=60, CMSInitiatingPermOccupancyFraction=60)
  • Llamar a System.gc()

Buscar operaciones de spam

Hay dos métodos para encontrar basura: recuento de referencias y análisis de accesibilidad.

Método de conteo de referencias: Es un algoritmo simple de recolección de basura. Su idea básica es agregar un contador de referencia a un objeto. Siempre que hay una referencia a él, el contador aumenta en 1; cuando la referencia expira, el contador disminuye en 1. Cuando el contador llega a 0, se puede considerar que el objeto ya no está referenciado y puede reciclarse. Sin embargo, el método de conteo de referencias no puede resolver el problema de las referencias circulares, es decir, se forma una estructura de anillo entre los objetos, lo que hace que sus contadores no sean 0, incluso si el programa ya no los usa.

Método de análisis de accesibilidad: es el principal método de implementación de los algoritmos modernos de recolección de basura. Su idea básica es partir de un grupo de objetos llamados "objetos raíz" (como variables globales, pilas, áreas de métodos) y, a través de una serie de relaciones de referencia, los objetos alcanzables se consideran "vivos" y los objetos inalcanzables se consideran basura. y necesita ser reciclado. Las referencias circulares formadas entre objetos también se manejan correctamente durante el análisis de accesibilidad porque no existe una cadena de referencia entre ellas y el objeto raíz.

4. Limpieza de basura

Introducción a los algoritmos de uso común.

Marcar-barrer

GC se divide en dos fases, marcar y barrer .

Primero marque todos los objetos reciclables y luego recicle todos los objetos marcados de manera uniforme una vez completado el marcado.

La desventaja es que se generarán fragmentos de memoria discontinuos después de borrarlos. Demasiada fragmentación dará como resultado la imposibilidad de encontrar suficiente memoria contigua cuando sea necesario asignar un objeto más grande cuando el programa se esté ejecutando, y el GC deberá activarse nuevamente.

Marcar-copiar

Divida la memoria en dos bloques según la capacidad y utilice solo un bloque a la vez. Cuando este bloque de memoria se agota, los objetos supervivientes se copian en otro bloque y luego el espacio de memoria utilizado se borra de inmediato. Esto hace posible reciclar la mitad del área de memoria cada vez sin tener que considerar problemas de fragmentación de la memoria, lo cual es simple y eficiente.

Las desventajas requieren el doble de espacio de memoria. Un método de optimización es utilizar áreas de Edén y Supervivientes. Los pasos específicos son los siguientes:

La relación de espacio de memoria predeterminada entre las áreas del Edén y de los Supervivientes es 8: 1: 1. Solo se utilizan el área del Edén y una de las áreas de los Supervivientes al mismo tiempo. Una vez completada la marca, copie los objetos supervivientes a otra área de supervivientes no utilizada (algunos objetos antiguos se actualizarán a la generación anterior).

 De esta manera, en comparación con el algoritmo ordinario de copia de marcas de dos espacios, solo se desperdicia el 10% del espacio de memoria, la razón es que, en la mayoría de los casos, quedan muy pocos objetos supervivientes después de un gc joven .

Mark-Compacto

El marcado y la clasificación también se dividen en dos etapas: primero, marque los objetos reciclables, luego mueva los objetos supervivientes a un extremo y luego limpie la memoria fuera del límite.

 Este método evita el problema de fragmentación del algoritmo de barrido de marcas y también evita el problema de espacio del algoritmo de copia.

Generalmente, después de que se ejecuta GC en la generación joven, una pequeña cantidad de objetos sobrevivirá y se utilizará el algoritmo de copia. La colección se puede completar con un pequeño costo de copiar los objetos supervivientes.

En la generación anterior, debido a la alta tasa de supervivencia de los objetos, la eficiencia de la copia de datos es baja cuando se utiliza el algoritmo de copia marcada y se desperdicia espacio. Por lo tanto, es necesario utilizar el algoritmo de barrido de marca o compacto de marca para el reciclaje.

Por lo tanto, generalmente puede usar primero el algoritmo de marca y borrado y luego usar el algoritmo de deflación de marca cuando la tasa de fragmentación es alta.

Algoritmo de recopilación generacional

Antecedentes del problema

De lo anterior, ninguno de los algoritmos básicos de recolección de basura es una solución mágica: tienen características diferentes y no pueden hacer frente a todos los escenarios. En la JVM moderna, a través del análisis de una gran cantidad de escenarios reales, se puede encontrar que los objetos en la memoria JVM se pueden dividir aproximadamente en dos categorías: un tipo de objetos, cuyo ciclo de vida es muy corto, como variables locales, temporales objetos, etc Otro tipo de objeto sobrevivirá durante mucho tiempo, como el objeto Conexión en la conexión larga de base de datos en la aplicación de usuario.

En la figura anterior, el eje vertical es el uso de memoria JVM y el eje horizontal es el tiempo. En la figura se puede encontrar que el ciclo de vida de la mayoría de los objetos es extremadamente corto y pocos objetos pueden sobrevivir después de la GC. A partir de esto nació la idea de generación. En JDK7, la máquina virtual Hotspot divide principalmente la memoria en tres grandes bloques: generación joven, generación anterior y generación permanente.

Descripción del área generacional

El principal análisis básico de clasificación regional es el siguiente:

Generación cenozoica: la nueva generación se divide principalmente en dos partes: área de Eden y área de Survivor, que se puede dividir en dos partes, S0 y S1. En esta área, el espacio es más pequeño que la generación anterior, el ciclo de vida de los objetos es corto y la GC es frecuente. Por lo tanto, en esta área se utilizan a menudo algoritmos de replicación marcada.

Generación anterior: el espacio general de la generación anterior es mayor, el ciclo de vida de los objetos es largo, la tasa de supervivencia es alta y el reciclaje es poco frecuente. Por lo tanto, es más adecuado para algoritmos de clasificación de marcas.

Generación permanente: la generación permanente también se denomina área de método, que almacena metainformación de clases e interfaces e información de cadenas internas. Reemplazado por metaespacio en JDK8.

Metaespacio: introducido después de JDK8, el área de método también existe en el metaespacio.

Proceso de ejecución del algoritmo de recolección de basura generacional.

  • Estado inicial: el objeto está asignado en el área de Eden y las áreas S0 y S1 están casi vacías.

  • A medida que se ejecuta el programa, se asignan cada vez más objetos en el área del Edén.

  • Cuando Eden no se puede liberar, se producirá MinorGC (es decir, YoungGC). En este momento, los objetos basura inalcanzables se identificarán primero, luego los objetos alcanzables se moverán al área S0 y los objetos inalcanzables se limpiarán. En este momento, el área del Edén está vacía. En este proceso, se utilizan el algoritmo de limpieza de marcas y el algoritmo de copia de marcas.

  • Cuando no se pueda liberar Eden, se activará minorGC nuevamente, al igual que en el paso anterior, márquelo primero. En este momento, puede haber objetos de basura en las áreas Eden y S0, pero el área S1 está vacía. En este momento, los objetos en las áreas de Eden y S0 se moverán directamente al área S1, y luego se limpiarán los objetos de basura en las áreas de Eden y S0. Después de esta ronda de MinorGC, las áreas Eden y S0 están vacías.

  • A medida que se ejecuta el programa, se asignará el espacio de Eden y se repetirá el proceso de MinorGC. Sin embargo, en este momento, el área S0 está vacía y las áreas S0 y S1 se intercambiarán. En este momento, los objetos supervivientes se ser transferido desde Eden y el área S1, pasar al área S0. Luego se limpiará la basura en las áreas de Eden y S1, y una vez completada esta ronda, estas dos áreas quedarán vacías.

  • Durante la ejecución del programa, aunque la mayoría de los objetos morirán rápidamente, todavía hay algunos objetos que sobreviven durante mucho tiempo. Para estos objetos, el movimiento repetido en las áreas S0 y S1 provocará una cierta sobrecarga de rendimiento y reducirá la eficiencia del GC. . Por lo tanto, se introdujo el comportamiento de promoción de objetos.

  • Cuando un objeto se encuentra entre las áreas Eden, S0 y S1 de la nueva generación, cada vez que se mueve de un área a otra, su edad aumentará en 1. Después de alcanzar un cierto umbral, si el objeto todavía está vivo, el objeto será promovido a la vejez.

  • Si también se asigna la generación anterior, se producirá MajorGC (es decir, GC completo). Dado que generalmente hay muchos objetos en la generación anterior, el algoritmo de complemento de marca lleva mucho tiempo, por lo que se producirá el fenómeno STW. Por lo tanto, la mayoría de las aplicaciones haga todo lo posible para reducir o evitar las causas de la GC completa.

Referencias, libros y enlaces.

1. El mecanismo operativo y el principio del recolector de basura clásico JVM - Blog de Kang Zhixing | Blog de kangzhixing

2. "Comprensión profunda de la máquina virtual Java"

3. "Algoritmo e implementación de recolección de basura"

 

Supongo que te gusta

Origin blog.csdn.net/xiaofeng10330111/article/details/130456197
Recomendado
Clasificación