¿Qué es Recolección de basura (Garbage Collection) de Java?

Vista aérea de Shanghai Lujiazui en nubes estratosféricas

¿Qué es Recolección de basura (Garbage Collection) de Java?

Garbage Collection o recolección de basura es una característica clave del lenguaje de programación Java que gestiona automáticamente la asignación y desasignación de memoria para los objetos que se crean en un espacio edén.

La Recolección de elementos no usados de Java permite a los desarrolladores centrarse en escribir código sin preocuparse por la gestión de la memoria, lo que convierte a Java en una opción popular para crear aplicaciones complejas y a gran escala. Sin embargo, comprender el funcionamiento de la Recolección de elementos no usados es esencial para que los desarrolladores de Java optimicen el rendimiento de su código y eviten errores comunes relacionados con la memoria.

En esta guía, se exploran los fundamentos de Garbage Collection de Java, incluidos sus beneficios, los diferentes tipos de recopiladores y las mejores prácticas a seguir durante la programación. Entonces, profundicemos y exploremos cómo funciona la recolección de basura

Las últimas noticias tecnológicas, respaldadas por los insights de expertos

Manténgase al día sobre las tendencias más importantes e intrigantes de la industria sobre IA, automatización, datos y más con el boletín Think. Consulte la Declaración de privacidad de IBM.

¡Gracias! Ya está suscrito.

Su suscripción se entregará en inglés. En cada boletín, encontrará un enlace para darse de baja. Puede gestionar sus suscripciones o darse de baja aquí. Consulte nuestra Declaración de privacidad de IBM para obtener más información.

¿Qué es OutofMemoryErrors?

OutofMemoryError es un tipo de error que ocurre cuando un programa o aplicación intenta asignar más memoria que la cantidad disponible. Este error se produce cuando la máquina virtual de Java (JVM) u otra plataforma se queda sin memoria al intentar ejecutar una aplicación.

Un OutOfMemoryError generalmente ocurre cuando una aplicación o programa intenta crear nuevos objetos, pero la JVM no puede asignar memoria para acomodarlos. Este error también puede ocurrir cuando una aplicación está usando demasiada memoria y no la está liberando correctamente.

Cuando ocurre un OutofMemoryError, la aplicación generalmente se bloquea y termina. Este error es común en programas que manejan grandes cantidades de metadatos, como aplicaciones de procesamiento de imágenes o video, o programas que manejan grandes bases de datos.

Para resolver este error, es posible que deba aumentar la cantidad de memoria disponible para la aplicación u optimizar el uso de memoria de la misma. Esto se puede hacer modificando los parámetros de JVM o empleando una herramienta de generación de perfiles de memoria para identificar fugas de memoria o uso ineficiente de memoria.

Desarrollo de aplicaciones

Entérese: desarrollo de aplicaciones empresariales en la nube

En este video, el Dr. Peter Haumer analiza cómo es el desarrollo de aplicaciones empresariales modernas en la nube híbrida y hace una demostración de diferentes componentes y prácticas, incluidos IBM Z Open Editor, IBM Wazi y Zowe.

¿Cómo funciona la recolección de basura de Java?

En Java, todos los objetos se almacenan en una acumulación, que es una parte de la memoria reservada para la asignación dinámica de objetos.n Cuando ya ninguna parte del programa hace referencia a un objeto, se vuelve elegible para la recolección de basura.

El recolector de basura de Java examina periódicamente la memoria de la acumulación para encontrar objetos que no se están usando. El proceso de recolección de basura implica varios pasos, incluidos el marcado, el barrido y la compactación.

  • Marcado: el primer paso de la recolección de basura consiste en marcar todos los objetos a los que el programa aún hace referencia. Esto se hace comenzando con un conjunto de objetos raíz, como variables globales, variables locales y parámetros de método, y luego rastreando todos los objetos a los que se puede acceder desde esas raíces. Los objetos a los que no se puede acceder desde las raíces se consideran elegibles para la recolección de basura.

  • Barrido: luego de la fase de marcado, el recolector de basura barre la acumulación de Java para identificar y recuperar la memoria que emplean los objetos a los que ya no se hace referencia. Esto implica desasignar la memoria que emplean los objetos no utilizados y agregarla de nuevo al grupo de memoria libre.

  • Compactación: en algunos algoritmos de recolección de basura, la fase de barrido es seguida por una fase de compactación, en la que la memoria empleada por los objetos restantes se reorganiza para minimizar la fragmentación. Esto implica acercar los objetos y crear bloques contiguos más grandes de memoria libre.

La virtual machine de Java (JVM) realiza automáticamente la recolección de basura, por lo que el programador no tiene que gestionar manualmente la memoria. El recolector de basura se ejecuta en un subproceso separado y normalmente funciona en segundo plano, por lo que no afecta la ejecución normal del programa.

Tipos de recolectores de elementos no usados de Java

Hay dos tipos principales de algoritmos de recolección de basura de Java: recolección de basura completa y recolección de basura incremental.

Recolección de elementos no usados completa o mayor

La recolección de basura completa es un proceso en el que un recolector de elementos no utilizados (una parte del sistema de tiempo de ejecución de un lenguaje de programación) busca en toda la memoria que emplea un programa y compila cualquier objeto que ya no esté usando el programa. Estos objetos se marcan como basura y son elegibles para su eliminación de la memoria.

La recolección completa de basura generalmente la realiza el sistema de tiempo de ejecución de un lenguaje de programación que emplea la gestión automática de memoria, como Java o Python. Durante el proceso, el recolector de basura pausa la ejecución del programa para realizar la búsqueda de objetos no utilizados, lo que puede provocar una ralentización temporal del rendimiento del programa.

La recolección de elementos no usados completa en general se activa cuando la cantidad de memoria empleada por un programa alcanza un umbral determinado o cuando el programa requiere un nuevo bloque de memoria y no hay suficiente memoria libre disponible. El objetivo de la recolección de elementos no usados completa es recuperar la memoria que el programa no necesita y ponerla a disposición para que la empleen otras partes del programa u otros programas que se ejecuten en la misma máquina.

Recolección de elementos no usados incremental o menor

La recolección de basura incremental es un tipo de técnica de administración de memoria que emplean los lenguajes de programación y los entornos de ejecución para recuperar automáticamente la memoria que un programa ya no necesita. Lo hace identificando objetos en la memoria que no se están utilizando para liberar la memoria que ocupan para que otras partes del programa puedan reutilizarla.

En la recolección incremental de basura, el recolector escanea periódicamente la memoria del programa en busca de objetos inalcanzables en la memoria de la acumulación de la generación joven. En lugar de detener la ejecución del programa durante este proceso de escaneo, el recolector de basura divide el proceso en partes pequeñas y manejables llamadas "incrementos". Durante cada incremento, el recolector de basura escanea una parte de la memoria del programa, identificando cualquier objeto que no sea necesario y lo marca como disponible para su reutilización.

Al usar incrementos, el recolector de basura puede recuperar memoria en pequeños fragmentos, sin interrumpir la ejecución del programa durante un periodo prolongado. Esto ayuda a garantizar que el programa siga respondiendo y no experimente pausas o demoras significativas como resultado del proceso de recolección de basura.

Sin embargo, la recolección de elementos no usados incremental puede ser menos eficiente que otros tipos de técnicas de recolección de elementos no usados, como el marcado y barrido o la recolección de elementos no usados generacional, porque requiere escaneos más frecuentes de la memoria del programa. Además, el uso de incrementos puede introducir cierta sobrecarga en la ejecución del programa, ya que el recolector de elementos no usados necesita mantener la información de estado entre cada incremento.

Beneficios de la recolección de basura de Java

En general, la recolección de basura de Java proporciona muchos beneficios que la convierten en una herramienta valiosa para los desarrolladores. Estos son algunos de los beneficios de emplear la recolección de basura de Java:

  1. No se requiere gestión manual de la memoria
  2. Evita fugas de memoria
  3. Asignación dinámica de memoria
  4. Mejor desempeño
  5. Optimización de la memoria
  • Sin gestión manual de la memoria: Con la recolección de basura, los desarrolladores no tienen que gestionar manualmente la asignación y desasignación de memoria. Esto significa que los programadores pueden centrarse más en escribir código y menos en gestionar la memoria, lo que puede ayudar a reducir errores y mejorar la productividad.

  • Evita fugas de memoria: la recolección de basura ayuda a prevenir fugas de memoria, que pueden ocurrir cuando un programa no libera memoria que ya no es necesaria. Esto puede hacer que el programa consuma más memoria de la necesaria, lo que ralentiza el rendimiento y, finalmente, se bloquea.

  • Asignación dinámica de memoria: La recolección de basura de Java permite la asignación dinámica de memoria, lo que significa que la memoria se asigna según sea necesario en tiempo de ejecución. Esto ayuda a prevenir errores de asignación de memoria y puede hacer que el programa sea más eficiente.

  • Mayor rendimiento: La recolección de basura puede ayudar a mejorar el rendimiento de un programa al reducir el tiempo dedicado a gestionar la memoria. Esto puede conducir a tiempos de ejecución más rápidos y un programa más receptivo.

  • Optimización de la memoria: la recolección de basura puede optimizar el uso de la memoria reutilizando la memoria que no emplea una parte del programa para otras partes del mismo. Esto puede ayudar a reducir el uso de memoria y mejorar la eficiencia general del programa.

Los desarrolladores se benefician de la capacidad de la recolección de basura de Java para administrar automáticamente la memoria, evitar fugas de memoria, habilitar la asignación dinámica de memoria, mejorar el rendimiento y optimizar el uso de la memoria. La recolección de basura puede ayudar a los desarrolladores a escribir programas mejores y más eficientes.

¿Qué eventos activan la recolección de basura de Java?

En Java, JVM (Java Virtual Machine) activa automáticamente la recolección de basura cuando determina que la acumulación se está llenando o cuando ha pasado cierto tiempo.

Hay varios eventos que pueden desencadenar la recolección de basura en Java:

  • Asignación de espacio de almacenamiento dinámico: cuando JVM necesita asignar memoria para un nuevo objeto y no hay suficiente espacio en el almacenamiento dinámico, se activa la recolección de basura para recuperar la memoria no utilizada o almacenarla en el espacio remanente.

  • Llamada al método System.gc(): puede solicitar explícitamente la recolección de basura llamando al método System.gc(), aunque no hay garantía de que se ejecute.

  • Umbral de generación anterior: la recolección de basura también se puede activar cuando el tamaño del almacenamiento del espacio de generación anterior (que almacena objetos de larga duración) alcanza un determinado umbral.

  • Umbral de PermGen/Metaspace: en versiones de Java anteriores a Java 8, la recolección de basura también se puede activar cuando el tamaño de las áreas de memoria de PermGen (generación permanente) o Metaspace (en Java 8 y posteriores) alcanza un umbral determinado.

  • Basado en el tiempo: a veces, la recolección de basura se puede activar en función de un intervalo de tiempo. Por ejemplo, JVM podría activar la recolección de basura cada hora o cada día, independientemente del uso de la memoria.

Vale la pena señalar que el comportamiento exacto de la recolección de basura en Java puede variar según la implementación y configuración de JVM.

Cómo solicitar JVM para ejecutar el recolector de basura

Para solicitar Java Virtual Machine (JVM) para ejecutar el recolector de basura, puede seguir estos pasos:

  1. Llamar al método System.gc() : este método se emplea para solicitar a JVM que ejecute el recolector de basura. No se garantiza que el recolector de basura se ejecute inmediatamente luego de acudir a este método.

  2. Emplee el método Runtime.getRuntime().gc(): este método es similar al método System.gc(), pero es menos probable que sea anulado por la implementación de JVM.
  3. Emplee el indicador -XX:+DisableExplicitGC JVM: este indicador deshabilita las solicitudes explícitas de recolección de basura. Esto significa que incluso si llama a System.gc() o Runtime.getRuntime().gc(), el recolector de basura no se activará.

Es importante tener en cuenta que en general no se recomienda solicitar explícitamente que se ejecute el recolector de elementos no usados, ya que la JVM está diseñada para administrar automáticamente la asignación de memoria y la recolección de elementos no usados. Las solicitudes explícitas de recolección de elementos no usados a veces pueden tener un impacto negativo en el rendimiento.

¿Cuándo es elegible un objeto para la recolección de basura?

Un objeto en un lenguaje de programación es elegible para la recolección de basura cuando ninguna parte del programa ya hace referencia a él. La recolección automática de elementos no usados es un proceso realizado por el entorno de tiempo de ejecución del lenguaje de programación para recuperar memoria.

En la mayoría de los lenguajes de programación modernos, la recolección de basura la realiza automáticamente el entorno de ejecución. Los algoritmos específicos que se emplean para la recolección de basura pueden variar en función del lenguaje de programación y la implementación, pero el principio general es el mismo: el entorno de ejecución explora periódicamente la acumulación (la parte de la memoria que se emplea para los objetos asignados dinámicamente) para identificar los objetos que ya no son accesibles desde cualquier objeto vivo en el programa. Una vez que se identifica que un objeto no es accesible, se marca como basura y su memoria se puede recuperar.

El momento exacto en que un objeto es elegible para la recolección de basura depende del algoritmo de recolección de basura específico que emplea el entorno de tiempo de ejecución. Algunos algoritmos son más agresivos que otros y pueden recuperar memoria más rápidamente, mientras que otros pueden retrasar la recolección de basura para optimizar el rendimiento. Sin embargo, en general, el programador no necesita preocuparse por gestionar la memoria manualmente, ya que el entorno de tiempo de ejecución se encarga de esto automáticamente.

¿Qué recolectores de basura están disponibles para Java?

Hay varios recolectores de basura de Java, que incluyen:

  1. Recolector de basura en serie
  2. Recolector de basura paralelo
  3. Recolector de barrido de marcas concurrentes (CMS)
  4. Recolector de basura G1
  • Recolector de basura en serie: El recolector en serie es el recolector de basura predeterminado en Java y generalmente se usa en aplicaciones pequeñas y medianas que no requieren alto rendimiento. Este tipo de recolector ayuda a evitar que ocurran los eventos comunes que “detienen el mundo”.

  • Recolector de basura paralelo: Está diseñado para aplicaciones de alto rendimiento y es particularmente útil en aplicaciones que requieren grandes montones porque emplea múltiples CPU para acelerar el proceso. Es importante tener en cuenta que este tipo de recopilador congela los subprocesos de la aplicación cuando ejecuta un recolector de basura.

  • Recopilador de barrido de marcas concurrente (CMS): el recopilador CMS está diseñado para aplicaciones que requieren tiempos de pausa cortos y es útil en aplicaciones que tienen muchos objetos activos.

  • Recolector de basura G1: el Recolector G1 está diseñado para grandes acumulaciones y puede manejar una combinación de objetos de corta y larga duración. Emplea varios subprocesos para escanear y compactar simultáneamente la acumulación.

Cada recolector de basura tiene sus propias fortalezas y debilidades, y la elección de qué recolector usar depende de las necesidades específicas de la aplicación. También es posible configurar y ajustar la configuración del recolector de basura para optimizar el rendimiento de una aplicación en particular.

¿Cuál es la diferencia entre la recolección de basura y la fuga de memoria?

La recolección de basura y las fugas de memoria están relacionadas con la gestión de memoria en los programas informáticos, pero tienen diferentes significados y participaciones.

Como ya se dijo, la recolección de basura suele realizarla el lenguaje de programación o el entorno de ejecución, y ayuda a garantizar que los programas no consuman más memoria de la necesaria. La recolección de basura identifica la memoria que está libre para ser empleada por otras partes del programa o por otros programas que se ejecutan en la computadora.

Por otro lado, una fuga de memoria ocurre cuando un programa no puede liberar la memoria que asignó, incluso cuando esa memoria ya no es necesaria. Como resultado, el programa continúa consumiendo memoria a lo largo del tiempo, lo que lleva al agotamiento final de la memoria disponible, y esto puede hacer que el programa o todo el sistema operativo se bloquee. Las fugas de memoria suelen ser causadas por errores en el programa y pueden ser difíciles de identificar y corregir.

En resumen, la recolección de basura es un proceso para liberar automáticamente memoria que ya no es necesaria. Las fugas de memoria se producen cuando un programa asigna memoria, pero no la libera, lo que provoca una acumulación gradual del uso de memoria.

Instana puede ayudarlo a monitorear el rendimiento de las aplicaciones Java

En conclusión, la Recolección de elementos no usados es un aspecto esencial de la programación Java que garantiza una gestión eficiente de la memoria al recuperar la memoria no utilizada. La observabilidad de Instana proporciona a los desarrolladores herramientas poderosas para monitorear y optimizar el proceso de recolección de elementos no usados en tiempo real.

Al usar Instana, los desarrolladores pueden identificar rápidamente fugas de memoria, optimizar la configuración de recolección de basura y solucionar problemas de rendimiento relacionados con la recolección de basura.

Gracias a las capacidades completas de supervisión de Instana, los desarrolladores pueden obtener insights detallados sobre el uso de la memoria y el comportamiento de la recolección de elementos no usados de sus aplicaciones Java, lo que les permite ofrecer software fiable y de alto rendimiento.

Siguiendo las mejores prácticas descritas en esta guía, los desarrolladores pueden usar Instana para optimizar el proceso de recolección de basura y mejorar el rendimiento general de sus aplicaciones Java. Con la observabilidad de Instana, los desarrolladores pueden anticipar cualquier problema que pueda surgir y asegurar que sus aplicaciones funcionen siempre al máximo.

Soluciones relacionadas
Desarrollo de aplicaciones impulsado por IA

watsonx.ai permite a los equipos de desarrollo de aplicaciones integrar perfectamente la IA en sus flujos de trabajo. Desde la creación de modelos hasta su despliegue, este completo kit de herramientas da soporte a todo el ciclo de vida de la IA.

Explorar watsonx.ai
IBM Z Development and Test Environment

Utilice una plataforma para el desarrollo de aplicaciones de mainframe, pruebas, demostración y entrenamiento en hardware x86.

Explorar el entorno de desarrollo Z
Soluciones de computación en la nube móvil

Descubra la plataforma de desarrollo de aplicaciones móviles de IBM para diseñar, crear prototipos y comercializar aplicaciones de manera rápida y sencilla.

Explorar la nube móvil
Dé el siguiente paso

Los servicios de consultoría de desarrollo de aplicaciones en la nube de IBM Cloud ofrecen orientación experta y soluciones innovadoras para agilizar su estrategia de nube. Colabore con los expertos en nube y desarrollo de IBM para modernizar, escalar y acelerar sus aplicaciones, y obtenga resultados transformadores para su empresa.

Conozca los servicios de desarrollo de aplicaciones Comience a crear con IBM Cloud de forma gratuita