¿Qué es el recolector de basura en Java?

103

Soy nuevo en Java y estoy confundido acerca del recolector de basura en Java. ¿Qué hace realmente y cuándo entra en acción? Describa algunas de las propiedades del recolector de basura en Java.

Subhransu Mishra
fuente
2
posible duplicado de recolección
Ian Ringrose
10
A veces es mejor leer el capítulo de un buen libro y esperar comprender un tema complejo a partir de la respuesta a una pregunta.
Ian Ringrose
4
@Ian Es una pregunta similar, pero no un duplicado. Y esa pregunta apesta a tarea.
NullUserException

Respuestas:

119

El recolector de basura es un programa que se ejecuta en la máquina virtual Java y que elimina los objetos que ya no están siendo utilizados por una aplicación Java. Es una forma de gestión automática de la memoria .

Cuando se ejecuta una aplicación Java típica, está creando nuevos objetos, como Strings y Files, pero después de cierto tiempo, esos objetos ya no se utilizan. Por ejemplo, eche un vistazo al siguiente código:

for (File f : files) {
    String s = f.getName();
}

En el código anterior, String sse crea en cada iteración del forbucle. Esto significa que en cada iteración, se asigna un poco de memoria para crear un Stringobjeto.

Volviendo al código, podemos ver que una vez que se ejecuta una sola iteración, en la siguiente iteración, el Stringobjeto que se creó en la iteración anterior ya no se usa más; ese objeto ahora se considera "basura".

Eventualmente, comenzaremos a recibir mucha basura y la memoria se usará para objetos que ya no se usan. Si esto continúa, eventualmente la máquina virtual Java se quedará sin espacio para crear nuevos objetos.

Ahí es donde interviene el recolector de basura.

El recolector de basura buscará objetos que ya no se estén usando y se deshará de ellos, liberando la memoria para que otros objetos nuevos puedan usar esa parte de la memoria.

En Java, la gestión de la memoria está a cargo del recolector de basura, pero en otros lenguajes como C, es necesario realizar la gestión de la memoria por su cuenta utilizando funciones como mallocyfree . La gestión de la memoria es una de esas cosas en las que es fácil cometer errores, lo que puede conducir a lo que se denomina pérdidas de memoria , lugares donde la memoria no se recupera cuando ya no se utiliza.

Los esquemas automáticos de administración de memoria, como la recolección de basura, hacen que el programador no tenga que preocuparse tanto por los problemas de administración de la memoria, para que pueda concentrarse más en desarrollar las aplicaciones que necesita desarrollar.

coobird
fuente
¿Sería cierto decir que una aplicación java que se ejecuta en una computadora tiene dos funcionalidades de recolección de basura? Uno con la máquina virtual Java. ¿Y luego uno en la máquina real que ejecuta Windows? (O cualquier otro sistema operativo)
Lealo
No, normalmente las aplicaciones Java se ejecutan solo si JRE está presente. Por lo tanto, solo se requiere la funcionalidad de recolección de basura de JVM. @Lealo
Am_I_Helpful
18

Libera la memoria asignada a los objetos que el programa ya no utiliza, de ahí el nombre "basura". Por ejemplo:

public static Object otherMethod(Object obj) {
    return new Object();
}

public static void main(String[] args) {
    Object myObj = new Object();
    myObj = otherMethod(myObj);
    // ... more code ...  
}

Sé que esto es extremadamente artificial, pero aquí, después de llamar, otherMethod()el original Objectcreado se vuelve inalcanzable, y eso es "basura" que se recolecta.

En Java, el GC se ejecuta automáticamente, pero también puede llamarlo explícitamente System.gc()e intentar forzar una recolección de basura importante. Como señala Pascal Thivent, realmente no debería tener que hacer esto y podría hacer más daño que bien (consulte esta pregunta ).

Para obtener más información, consulte la entrada de wikipedia sobre recolección de basura y ajuste de recolección de basura (de Oracle)

NullUserException
fuente
1
AFAIK System.gc()no obliga a GC a ejecutarse.
Itay Karo
1
+1 para el buen código de ejemplo. Tenga en cuenta que es perfectamente válido para el GC destruir myObjantes de que otherMethodse realice la llamada a , porque myObjya no es accesible en ese punto.
Billy ONeal
@Italia Creo que eso es específico de la implementación.
NullUserException
2
Creo que uno no debería llamar System.gc(), el objetivo de tener un GC es no tener que hacer eso.
Pascal Thivent
con el análisis de escape ( en.wikipedia.org/wiki/Escape_analysis ), es posible que la JVM ni siquiera asigne el objeto en primer lugar en este ejemplo. Toda la creación del objeto puede (en teoría) optimizarse. Depende de la implementación, por supuesto.
mikera
15

Un objeto se vuelve elegible para la recolección de basura o GC si no se puede acceder a él desde ningún hilo en vivo o por referencias estáticas.

En otras palabras, puede decir que un objeto se vuelve elegible para la recolección de basura si todas sus referencias son nulas. Las dependencias cíclicas no se cuentan como referencia, por lo que si el objeto A tiene una referencia al objeto B y el objeto B tiene una referencia al objeto A y no tienen ninguna otra referencia en vivo, entonces tanto los objetos A como B serán elegibles para la recolección de basura.


Generaciones de montón para recolección de basura -

Los objetos Java se crean Heapy Heapse dividen en tres partes o generaciones para la recolección de basura en Java, estos se denominan Generación joven (nueva), Generación permanente (antigua) y Área permanente del montón.

Espacio de montón de Java New Generation se divide en tres partes conocidas como espacio Eden, espacio Survivor 1 y Survivor 2. Cuando un objeto se crea por primera vez en un montón, se crea en una nueva generación dentro del espacio Edén y, después de la recolección de basura menor posterior, si un objeto sobrevive, se mueve al sobreviviente 1 y luego al sobreviviente 2 antes de que la recolección de basura principal mueva ese objeto a la generación anterior o titular .

El espacio permanente de Java Heap es donde JVM almacena metadatos sobre clases y métodos, grupo de cadenas y detalles de nivel de clase.

Generaciones de montón para recolección de basura

Consulte aquí para obtener más información: Recolección de basura


No puede obligar a JVM a ejecutar Garbage Collection, aunque puede realizar una solicitud utilizando el método System.gc()o Runtime.gc().

En java.lang.System

public static void gc() {
    Runtime.getRuntime().gc();  
}

En java.lang.Runtime

public native void gc();  // note native  method

Algoritmo de marcado y barrido -

Este es uno de los algoritmos más populares utilizados por la recolección de basura. Cualquier algoritmo de recolección de basura debe realizar 2 operaciones básicas. Uno, debería poder detectar todos los objetos inalcanzables y, en segundo lugar, debe recuperar el espacio de pila utilizado por los objetos basura y hacer que el espacio esté disponible nuevamente para el programa.

Las operaciones anteriores son realizadas por Mark and Sweep Algorithm en dos fases:

  1. Fase de marca
  2. Fase de barrido

lea aquí para más detalles - Algoritmo de marcado y barrido

roottraveller
fuente
6

recolector de basura implica que los objetos que el programa ya no necesita son "basura" y pueden desecharse.

Nik
fuente
6

Garbage Collector es parte de JRE que se asegura de que el objeto al que no se hace referencia se libere de la memoria.
Por lo general, se ejecuta cuando la aplicación se queda sin memoria. AFAIK tiene un gráfico que representa los vínculos entre los objetos y los objetos aislados se pueden liberar.
Para ahorrar rendimiento, los objetos actuales agrupados en generaciones, cada vez que GC escanea un objeto y descubre que todavía se hace referencia, su recuento de generación se incrementa en 1 (a un valor máximo máximo, 3 o 4, creo), y la nueva generación se escanea primero (cuanto más corto sea el objeto en la memoria, más probablemente ya no sea necesario), por lo que no todos los objetos se escanean cada vez que se ejecuta el GC.
lea esto para obtener más información.

Itay Karo
fuente
@quantumSoup, ¿estás seguro de esto? Creo que algún tipo de recolección de basura (una más cara) solo ocurre cuando el montón se llena.
Pablo Fernandez
2
@quantumSoup: eso depende de la implementación de GC de JRE. En muchos casos, el GC no funciona constantemente. En cambio, se ejecuta cuando su aplicación no puede asignar un objeto porque el montón está lleno. Las JVM de HotSpot recientes incluyen un GC paralelo, pero no está habilitado de forma predeterminada.
Stephen C
Esta respuesta se concentra demasiado en el mecanismo. La pregunta era "¿Qué es el recolector de basura", no "Cómo funciona el recolector de basura"
Billy ONeal
@quantum: neutralizó su -1, porque: Aprendizaje, es decir, para qué sirve esta página, ¿no? Para aprender es necesario cometer errores. Castigar los errores hace que la gente no aprenda. Espero que puedas estar de acuerdo en ese punto. Y tal vez cometiste un error aquí.
erikbwork
1
@erikb: Según esa lógica, nunca habría ningún voto negativo. Y los votos negativos son necesarios para descartar respuestas relativamente pobres. El OP es obviamente un principiante, y el funcionamiento interno específico del GC simplemente no es importante para la pregunta formulada. Dado que esta respuesta no responde a la pregunta formulada (responde a otra diferente), los votos negativos están perfectamente justificados.
Billy ONeal
3

El recolector de basura permite que su computadora simule una computadora con memoria infinita. El resto es solo un mecanismo.

Para ello, detecta cuándo ya no se puede acceder a fragmentos de memoria desde su código y devuelve esos fragmentos a la tienda gratuita.

EDITAR: Sí, el enlace es para C #, pero C # y Java son idénticos en este sentido.

Billy ONeal
fuente
En realidad, hay una pregunta en SO sobre la diferencia entre java y GC de C #: stackoverflow.com/questions/492703/c-vs-java-garbage-collector
NullUserException
3

Mucha gente piensa que la recolección de basura recolecta y desecha objetos muertos.
En realidad, ¡la recolección de basura de Java está haciendo lo contrario! Los objetos vivos se rastrean y todo lo demás se designa como basura.

Cuando un objeto ya no se usa, el recolector de basura recupera la memoria subyacente y la reutiliza para la futura asignación de objetos. Esto significa que no hay una eliminación explícita y no se devuelve memoria al sistema operativo. Para determinar qué objetos ya no están en uso, la JVM ejecuta de forma intermitente lo que se llama muy acertadamente un algoritmo de marca y barrido.

Consulte esto para obtener más información detallada: http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx

VdeX
fuente
1

Para decirlo en los términos más simples que incluso un no programador puede entender, cuando un programa procesa datos, crea datos intermedios y espacio de almacenamiento (variables, matrices, ciertos metadatos de objetos, etc.) para esos datos.

Cuando se accede a estos objetos a través de funciones o sobre un cierto tamaño, se asignan desde un montón central. Luego, cuando ya no se necesiten, es necesario limpiarlos.

Hay algunos artículos muy buenos en línea sobre cómo funciona esto, así que solo cubriré la definición muy básica.

El GC es básicamente la función que realiza esta limpieza. Para hacer esto, borra las entradas de la tabla a las que no hace referencia ningún objeto activo, eliminando efectivamente los objetos, luego copia y compacta la memoria. Es un poco más complicado que esto, pero entiendes la idea.

El gran problema es que algunas partes de este proceso a menudo requieren que toda la máquina virtual de Java deba detenerse temporalmente para que se lleve a cabo, además de que todo este proceso consume mucho ancho de banda de memoria y procesador. Las diversas opciones de GC y las opciones de ajuste para cada uno están diseñadas para equilibrar estos diversos problemas con todo el proceso de GC.

Robert Wm Ruedisueli
fuente
0

La recolección de basura en Java (y también en otros lenguajes / plataformas) es una forma para que el entorno de tiempo de ejecución de Java (JRE) reutilice la memoria de los objetos de Java que ya no son necesarios. De manera simplista, cuando el JRE se inicia inicialmente, solicita al sistema operativo (O / S) una cierta cantidad de memoria. A medida que el JRE ejecuta su (s) aplicación (es), usa esa memoria. Cuando su aplicación termina de usar esa memoria, el "recolector de basura" de JRE aparece y reclama esa memoria para que la utilicen diferentes partes de sus aplicaciones existentes. El "recolector de basura" de JRE es una tarea en segundo plano que siempre se está ejecutando y trata de seleccionar las horas en las que el sistema está inactivo para continuar con sus ejecuciones de basura.

Una analogía del mundo real sería el de los basureros que vienen a tu casa y recogen tu basura reciclable ... eventualmente, es reutilizada de otras formas por ti y / o otras personas.

Al Dass
fuente
0

El recolector de basura se puede ver como un administrador de recuento de referencias. si se crea un objeto y su referencia se almacena en una variable, su recuento de referencias aumenta en uno. durante el curso de la ejecución si esa variable está asignada con NULL. el recuento de referencias para ese objeto disminuye. por lo que el recuento de referencia actual para el objeto es 0. Ahora, cuando se ejecuta el recolector de basura, comprueba los objetos con el recuento de referencia 0. y libera los recursos asignados a él.

La invocación del recolector de basura está controlada por políticas de recolección de basura.

Puede obtener algunos datos aquí. http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

bala sreekanth
fuente
1
El recuento de referencias es una forma pésima de implementar GC. No creo que ninguna implementación importante de JVM use esto.
NullUserException
0

El recolector de basura es un componente de jvm.

Se utiliza para recolectar basura cuando la CPU se libera.

Aquí basura significa objetos no utilizados que se ejecuta en segundo plano del programa principal

para monitorear el estado del programa principal.

Pulipati Prasadarao
fuente
0

La recolección automática de basura es el proceso de mirar la memoria del montón, identificar qué objetos están en uso y cuáles no, y eliminar los objetos no usados. Un objeto en uso, o un objeto referenciado, significa que alguna parte de su programa aún mantiene un puntero a ese objeto. Un objeto no utilizado, o un objeto no referenciado, ya no es referenciado por ninguna parte de su programa. Por lo tanto, la memoria utilizada por un objeto no referenciado se puede recuperar.

En un lenguaje de programación como C, asignar y desasignar memoria es un proceso manual. En Java, el recolector de basura maneja automáticamente el proceso de desasignación de memoria. Consulte el enlace para una mejor comprensión. http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

Shashank Shankaranand
fuente
0

La recolección de basura se refiere al proceso de liberar automáticamente memoria en el montón eliminando objetos que ya no son accesibles en su programa. El montón es una memoria a la que se hace referencia como almacenamiento gratuito, representa una gran cantidad de memoria no utilizada asignada a su aplicación Java.

Aamir M Meman
fuente
1
No utilice formato de cita para el texto que no se cita, y si se cita, debe citar la fuente.
Marqués de Lorne
0

Los principios básicos de la recolección de basura son encontrar objetos de datos en un programa al que no se puede acceder en el futuro y recuperar los recursos utilizados por esos objetos. https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29

Ventajas

1) Se salva de errores, que se producen cuando se libera una parte de la memoria mientras todavía hay punteros hacia ella, y se desreferencia a uno de esos punteros. https://en.wikipedia.org/wiki/Dangling_pointer

2) Errores libres dobles, que ocurren cuando el programa intenta liberar una región de memoria que ya ha sido liberada, y quizás ya haya sido asignada nuevamente.

3) Previene ciertos tipos de pérdidas de memoria, en las que un programa no logra liberar memoria ocupada por objetos que se han vuelto inalcanzables, lo que puede llevar al agotamiento de la memoria.

Desventajas

1) Consumo de recursos adicionales, impactos en el desempeño, posibles estancamientos en la ejecución del programa e incompatibilidad con la gestión manual de recursos. La recolección de basura consume recursos informáticos para decidir qué memoria liberar, aunque el programador ya conozca esta información.

2) El momento en que la basura se recolecta realmente puede ser impredecible, lo que resulta en paradas (pausas para cambiar / liberar memoria) dispersas a lo largo de una sesión. Los atascos impredecibles pueden ser inaceptables en entornos de tiempo real, en el procesamiento de transacciones o en programas interactivos.


Tutorial de Oracle http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

La recolección de basura es el proceso que identifica qué objetos están en uso y cuáles no, y elimina los objetos no utilizados.

En lenguajes de programación como C, C ++, asignar y liberar memoria es un proceso manual.

int * array = new int[size];
processArray(array); //do some work.
delete array; //Free memory

El primer paso del proceso se llama marcado. Aquí es donde el recolector de basura identifica qué piezas de memoria están en uso y cuáles no.

Paso 2a. La eliminación normal elimina los objetos no referenciados dejando los objetos referenciados y los punteros al espacio libre.

Para mejorar el rendimiento, queremos eliminar los objetos no referenciados y también compactar el resto de los objetos referenciados. Queremos mantener juntos los objetos referenciados, por lo que será más rápido asignar nueva memoria.

Como se indicó anteriormente, tener que marcar y compactar todos los objetos en una JVM es ineficiente. A medida que se asignan más y más objetos, la lista de objetos crece y crece, lo que lleva a un tiempo de recolección de basura cada vez más largo.

Continúe leyendo este tutorial y sabrá cómo GC acepta este desafío.

En resumen, hay tres regiones del montón, YoungGeneration para objetos de corta duración, OldGeneration para objetos de período largo y PermanentGeneration para objetos que viven durante la vida de la aplicación, por ejemplo, clases, bibliotecas.

Yan Khonski
fuente
0

Como los objetos son asignados dinámicamente por el nuevo operador, puede preguntar cómo se destruyen estos objetos y cómo se libera la memoria ocupada. En otros lenguajes como C ++, es necesario liberar los objetos asignados manualmente de forma dinámica mediante el operador de eliminación. Java tiene un enfoque diferente; maneja automáticamente la desasignación. La técnica se conoce como recolección de basura .

Funciona así: cuando no hay referencias a un objeto, se asume que este objeto ya no es necesario y se puede recuperar la memoria ocupada por el objeto. No es necesario destruir objetos explícitamente como en C ++. La recolección de basura ocurre esporádicamente durante la ejecución del programa; No sucede simplemente porque hay uno o más objetos que ya no se utilizan. Además, varias implementaciones de tiempo de ejecución de Java tienen diferentes enfoques para la recolección de basura, pero la mayoría de los programadores no tienen que preocuparse por esto cuando escriben programas.

Amarildo
fuente
-2

La recolección automática de basura es un proceso en el que la JVM se deshace o mantiene ciertos puntos de datos en la memoria para finalmente liberar espacio para el programa en ejecución. La memoria se envía primero a la memoria del montón, que es donde el recolector de basura (GC) hace su trabajo, luego se decide terminar o guardar. Java asume que no siempre se puede confiar en el programador, por lo que termina los elementos que cree que no necesita.

Lopes_CP_2579
fuente