works recolector how generations garbagecollector forzar example español ejemplo como collector basura activar java garbage-collection

how - Recolector de basura de Java: ¿cuándo se recoge?



java gc generations (6)

Cuando JVM no tiene espacio de memoria necesario para ejecutar, el recolector de basura ejecutará y eliminará los objetos innecesarios y asignará memoria para JVM.

Los objetos innecesarios son los objetos que no tienen ninguna referencia (dirección) para ello.

Hay principalmente 4 puntos para los objetos elegibles para el recolector de basura.

  1. Referencia nula

    El recolector de basura puede eliminar un objeto cuando la variable de referencia del objeto se asigna nulo, ya que es el valor

    A a = new A(); a = null;

  2. Reasignación

    Cuando se asigna otro objeto a la variable de referencia de un objeto, el recolector de basura puede eliminar el objeto referenciado anterior.

    A a = new A(100); a =new A(200);

  3. Alcance local

    Si se crea un objeto dentro de un bloque, ese objeto es elegible para el recolector de basura al costado de ese bloque.

    if(condition){ A a = new A(); }

  4. Aislamiento

    Un objeto puede referir a otro objeto, pero debe haber al menos una variable de referencia (dirección) para estos objetos en la pila; de lo contrario, todos esos objetos son elegibles para el recolector de basura.

    class A{ A r; A(int i){ //something } } A a1 = new A(100); a1.r = new A(101); a1.r.r = new A(102); a1.r.r.r = a1; a1 = null //all ojects are eligible to garbage collector

¿Qué es lo que determina cuándo se recoge realmente el recolector de basura? ¿Sucede después de un cierto tiempo o después de que se haya agotado una cierta cantidad de memoria? ¿O hay otros factores?


Depende mucho de qué recolector de basura estés usando en realidad, cómo está afinado, y una gran cantidad de entradas.

Para ver un resumen del HotSpot Garbage Collector (el común que viene con Java) y cómo está sintonizado, puede consultar este enlace


El recolector de elementos no utilizados se ejecuta cuando necesita recursos y de manera regular que usted puede influir diciéndole cuándo es un buen momento para gastar CPU en la recopilación, utilizando System.gc()

Puede ayudar al recolector de basura anulando referencias explícitamente, por ejemplo, dando a sus objetos métodos init() que asignan recursos y métodos de cleanup() que limpian explícitamente esos recursos y anulan sus referencias. Al anular las referencias usted mismo, evita que el recolector de basura tye tenga que buscar grupos de obects que tienen más rutas a una raíz.


Esto depende completamente de la JVM real y de lo que elija hacer, y básicamente está fuera de sus manos como programador. Los expertos acérrimos con barba gris pueden querer decirle a la JVM que lo saben mejor, pero para los simples mortales, esto debería considerarse una magia negra mejor dejada en paz.

Lo que debería preocuparle es si puede mantener el ritmo que sus programas crean y descarta objetos. Si no, todo su programa se detiene mientras ocurre la limpieza global. Eso resulta en tiempos de respuesta muy malos, pero rara vez ocurre en las JVM modernas en las computadoras modernas.

Si tiene curiosidad sobre lo que sucede en su programa y cuándo, investigue la herramienta "jvisualvm" en las versiones recientes de Java 6 JDK. Es realmente genial para mirar por dentro.


Se ejecuta cuando determina que es hora de ejecutar. Una estrategia común en recolectores de basura generacionales es ejecutar el recopilador cuando falla una asignación de memoria de generación-0. Es decir, cada vez que asigna un pequeño bloque de memoria (los bloques grandes normalmente se colocan directamente en generaciones "anteriores"), el sistema verifica si hay suficiente espacio libre en el montón gen-0, y si no hay, se ejecuta el CG para liberar espacio para que la asignación tenga éxito. Los datos antiguos se mueven al gen-1 y, cuando se agota el espacio, el GC ejecuta una recopilación sobre eso, actualizando los datos que han estado más tiempo en el gen-2 y así sucesivamente. Entonces el GC no solo "corre". Puede ejecutarse solamente en el gen-0 heap (y la mayoría de las colecciones lo harán), o podría verificar cada generación si realmente tiene que liberar mucha memoria (lo cual solo es necesario con bastante poca frecuencia).

Pero esto está lejos de ser la única estrategia. Un GC simultáneo se ejecuta en segundo plano, limpiando mientras el programa se está ejecutando. Algunos GC pueden ejecutarse como parte de cada asignación de memoria. Un recolector incremental podría hacer eso, escaneando algunos objetos en cada asignación de memoria.

Todo el punto en un recolector de basura es que debería hacer lo suyo sin requerir ninguna entrada del usuario. Entonces, en general, no puedes, y no debes, predecir cuándo se ejecutará.

Creo que Suns JVM ganó un GC generacional no hace mucho tiempo (tal vez v1.6? No he codificado Java por eras, así que no estoy seguro de esto, pero recuerdo haberme sorprendido no hace mucho tiempo, cuando uno de los puntos de venta para la nueva versión era "un GC generacional". No menos porque .NET ha tenido uno desde el día 1.)

Otras JVM son, por supuesto, libres de elegir cualquier estrategia que les guste.

EDITAR: La parte anterior sobre Java y GC generacional no es verdadera. Vea abajo para más detalles:

Las máquinas virtuales 1.0 y 1.1 utilizaban un recopilador de barrido de marca, que podía fragmentar el montón después de una recolección de basura. A partir de Java 1.2, las máquinas virtuales se cambiaron a un colector generacional, que tiene un comportamiento de desfragmentación mucho mejor (consulte la teoría y la práctica de Java: recolección y rendimiento de basura ).

Entonces Java en realidad tiene un GC generacional por años. Lo nuevo en Java 6 es el recolector de basura Garbage-First (G1) que está disponible en Java 6u14. De acuerdo con el artículo que reclama el lanzamiento en 1.6.0_14 : No está habilitado por defecto. El colector paralelo sigue siendo el GC predeterminado y es el GC más eficiente para el uso doméstico común. G1 está destinado a ser una alternativa para el colector simultáneo. Está diseñado para ser más predecible y permitir una asignación rápida con diseño de regiones de memoria.


  • Depende de la forma en que se compile el programa JIT.
  • Desde afuera, definitivamente no podemos decir cuándo se ejecutará.
  • Sigue algún algoritmo que depende de ese GC particular.
  • La máquina virtual Java se ejecuta en la máquina cliente con algo de memoria virtual en caso de que el valor predeterminado de Windows sea de 4 GB. También depende de esa memoria virtual gratuita en ese momento particular.

Puede probar este pequeño programa para verificar el comportamiento de GC

public class GCTest { final int NELEMS = 50000; void eatMemory() { int[] intArray = new int[NELEMS]; for (int i=0; i<NELEMS; i++) { intArray[i] = i; } } public static void main (String[] args) { GCTest gct = new GCTest(); // Step 1: get a Runtime object Runtime r = Runtime.getRuntime(); // Step 2: determine the current amount of free memory long freeMem = r.freeMemory(); System.out.println("free memory before creating array: " + freeMem); // Step 3: consume some memory gct.eatMemory(); // Step 4: determine amount of memory left after consumption freeMem = r.freeMemory(); System.out.println("free memory after creating array: " + freeMem); // Step 5: run the garbage collector, then check freeMemory r.gc(); freeMem = r.freeMemory(); System.out.println("free memory after running gc(): " + freeMem); } }

salida posible: puede ser diferente en su caso

free memory before creating array: 4054912 free memory after creating array: 3852496 free memory after running gc(): 4064184

Consulte este enlace http://www.devdaily.com/java/edu/pj/pj010008/