Garbage Collector

Garbage Collector

Para comprender completamente cómo funciona la recolección de basura en Java, es importante conocer las diferentes generaciones en la memoria (heap), las cuales ayudan a hacer la recolección de basura más eficiente. Estas generaciones se dividen en los siguientes tipos de espacios:

  • Eden (Edén): El espacio eden en Java es un pool de memoria donde se crean los objetos. Cuando el espacio eden está lleno, el recolector de basura elimina los objetos si ya no se están utilizando o los mueve al espacio de supervivencia si todavía están en uso. Este espacio se considera parte de la generación joven (young generation) en el montón de memoria.
  • Survivor (Superviviente): Hay dos espacios de supervivencia en la JVM: survivor cero y survivor uno. Este espacio también es parte de la generación joven.
  • Tenured (Tenured o Antiguo): El espacio tenured es donde se almacenan los objetos de larga duración. Los objetos se mueven eventualmente a este espacio si sobreviven a cierto número de ciclos de recolección de basura. Este espacio es mucho más grande que el espacio eden y el recolector de basura lo verifica con menos frecuencia. Este espacio se considera la generación antigua (old generation) en el montón de memoria.

img_1.png

img_2.png

¿Cómo hacen que la recolección de basura sea más eficiente estos diferentes espacios?

La recolección de basura ocurre con mayor frecuencia en el espacio eden porque muchos objetos nuevos no necesitan permanecer en memoria por mucho tiempo. Sin embargo, no tendría sentido que el recolector de basura siga verificando una y otra vez objetos que no han sido recolectados, especialmente si un objeto necesita permanecer en el heap por un largo período. Esto sería un uso ineficiente del recolector. Al mover los objetos a los espacios de supervivencia y tenured, el recolector de basura sabe que hay una mayor probabilidad de que los objetos allí necesiten permanecer en memoria, por lo que revisa esas áreas con menos frecuencia. Como el espacio tenured es mucho más grande que el espacio eden, se llena con menos regularidad y el recolector de basura no lo revisa tanto. La posible desventaja es que el espacio tenured es más propenso a fugas de memoria, ya que no se verifica con tanta frecuencia.

Los ciclos de recolección de basura en la generación joven (espacios eden y superviviente) se consideran minor garbage collection. Los ciclos de recolección de basura en la generación antigua (espacio tenured) se conocen como old garbage collection o major garbage collection, porque toma más tiempo que la recolección de basura menor. Como se podría suponer, el ciclo de recolección de basura menor es un proceso más simple y rápido que el de la recolección de basura mayor, lo cual tiene sentido porque ocurre con mucha más frecuencia y necesita ser eficiente.

En versiones anteriores de Java (antes de Java 8), existía una tercera área de memoria conocida como permanent generation (perm gen o PermGen) que incluía metadatos necesarios para la JVM. Sin embargo, la generación permanente fue eliminada en Java 8.

El proceso de recolección de basura en Java utiliza un algoritmo mark-and-sweep. Así es como funciona:

Hay dos fases en este algoritmo: mark y sweep. Cuando se crea un objeto en Java en el heap, tiene un bit de marcado que se establece en 0 (falso). Durante la fase de marcado, el recolector de basura recorre los árboles de objetos comenzando desde sus raíces. Cuando un objeto es accesible desde la raíz, el bit de marcado se establece en 1 (verdadero). Mientras tanto, los bits de marcado de los objetos inalcanzables permanecen sin cambios. Durante la fase de barrido, el recolector de basura recorre el heap, recuperando la memoria de todos los elementos con un bit de marcado de 0 (falso).