¿Cómo forzar la recolección de basura en Java?

¿Es posible forzar la recolección de basura en Java, incluso si es complicado hacerlo? Sé sobre System.gc(); y Runtime.gc(); pero solo sugieren hacer GC. ¿Cómo puedo forzar GC?

Su mejor opción es llamar a System.gc() que simplemente es una pista para el recolector de basura que desea que haga una colección. Sin embargo, no hay forma de forzar la recostackción inmediata ya que el recolector de basura no es determinista.

La biblioteca jlibs tiene una buena clase de utilidad para la recolección de basura . Puede forzar la recolección de basura utilizando un pequeño truco ingenioso con objetos WeakReference .

RuntimeUtil.gc () de los jlibs:

  /** * This method guarantees that garbage collection is * done unlike {@link System#gc()} */ public static void gc() { Object obj = new Object(); WeakReference ref = new WeakReference(obj); obj = null; while(ref.get() != null) { System.gc(); } } 

La mejor (si no única) forma de forzar un GC sería escribir una JVM personalizada. Creo que los recolectores de basura son conectables, por lo que probablemente solo puedas elegir una de las implementaciones disponibles para ajustarla.

Nota: esta NO es la respuesta fácil.

Al usar la interfaz de la Máquina-herramienta Virtual Java ™ (JVM TI) , la función

 jvmtiError ForceGarbageCollection(jvmtiEnv* env) 

“Forzará a la VM a realizar una recolección de basura”. JVM TI forma parte de JavaTM Platform Debugger Architecture (JPDA) .

es casi posible obligarlo a que tenga que llamar a métodos en el mismo orden y al mismo tiempo estos son:

 System.gc (); System.runFinalization (); 

incluso si solo hay un objeto para limpiar el uso de estos dos métodos al mismo tiempo, obligue al recolector de elementos no utilizados a utilizar el método finalise() del objeto inalcanzable, liberando la memoria asignada y haciendo lo que indica el método finalize() .

SIN EMBARGO , es una práctica terrible utilizar el recolector de basura porque el uso de este podría introducir una carga excesiva en el software que puede ser incluso peor que en la memoria, el recolector de basura tiene su propio hilo que no es posible controlar más dependiendo de el algoritmo utilizado por el gc podría tomar más tiempo y se considera muy ineficiente, usted debe verificar su software si es peor con la ayuda del gc porque definitivamente está roto, una buena solución no debe depender del gc.

NOTA: solo para tener en cuenta que esto funcionará solo si en el método de finalización no es una reasignación del objeto, si esto sucede el objeto se mantendrá vivo y tendrá una resurrección que es técnicamente posible.

Debajo de la documentación de OutOfMemoryError , declara que no se lanzará a menos que la VM no haya recuperado la memoria después de una recolección completa de basura. Entonces, si continúa asignando memoria hasta que obtenga el error, ya habrá forzado una recolección completa de basura.

Presumiblemente, la pregunta que realmente quería hacer era “¿cómo puedo reclamar la memoria que creo que debería reclamar por la recolección de basura?”

Para solicitar GC manualmente (no desde System.gc ()):

  1. Ir a la carpeta bin en JDK eg.-C: \ Program Files \ Java \ jdk1.6.0_31 \ bin
  2. Abra jconsole.exe
  3. Conéctese al proceso local deseado.
  4. Vaya a la pestaña de memoria y haga clic en realizar GC.

.gc es un candidato para su eliminación en futuras versiones: un ingeniero de Sun comentó una vez que quizás menos de veinte personas en el mundo realmente saben cómo usar .gc () – Hice un trabajo anoche durante unas horas en una central / crítica estructura de datos con datos generados por SecureRandom, en algún lugar que pasó de los 40,000 objetos, la VM se ralentizaría como si se le hubieran acabado los punteros. Claramente, se estaba ahogando en las tablas de punteros de 16 bits y exhibió el comportamiento clásico de “falla de la maquinaria”.

Intenté -Xms y demás, mantuve un poco el ritmo hasta que funcionó a aproximadamente 57, xxx algo. Luego se ejecutaría gc yendo de decir 57.127 a 57.128 después de un gc () – aproximadamente el ritmo de hinchazón de código en el campo Easy Money.

Su diseño necesita una revisión fundamental, probablemente un enfoque de ventana deslizante.

La especificación de JVM no dice nada específico sobre la recolección de basura. Debido a esto, los proveedores son libres de implementar GC en su camino.

Entonces esta vaguedad causa incertidumbre en el comportamiento de recolección de basura. Debería verificar los detalles de su JVM para conocer los enfoques / algoritmos de recolección de basura. También hay opciones para personalizar el comportamiento también.

Útil para lote / crontab:

jdk1.7.0 / bin / jcmd GC.run

Ver :

Si necesita forzar la recolección de basura, quizás deba considerar cómo administra los recursos. ¿Estás creando objetos grandes que persisten en la memoria? ¿Estás creando objetos grandes (p. Ej., Clases de gráficos) que tienen una interfaz Disposable y que no invocan a dispose() cuando terminan con ella? ¿Estás declarando algo a nivel de clase que solo necesitas con un solo método?

Sería mejor si describiera la razón por la cual necesita recolección de basura. Si está utilizando SWT, puede disponer recursos tales como Image y Font para liberar memoria. Por ejemplo:

 Image img = new Image(Display.getDefault(), 16, 16); img.dispose(); 

También hay herramientas para determinar los recursos no expuestos.

Utilice Runtime.getRuntime().gc() o use el método de utilidad System.gc()

Realmente, no te entiendo. Pero para ser claros acerca de la “Creación infinita de objetos”, quise decir que hay un pedazo de código en mi gran sistema de creación de objetos que se maneja y está vivo en la memoria, ¡no pude obtener este fragmento de código en realidad, solo gesto!

Esto es correcto, solo gesto. Usted tiene casi las respuestas estándar ya dadas por varios carteles. Tomemos uno por uno:

  1. No pude obtener este fragmento de código en realidad

Correcto, no hay jvm real, es solo una especificación, un grupo de ciencias de la computación que describe un comportamiento deseado … Recientemente investigué para inicializar objetos Java a partir de código nativo. Para obtener lo que desea, la única forma es hacer lo que se denomina nulidad agresiva. Los errores si se hacen mal son tan malos que si se hace mal, tenemos que limitarnos al scope original de la pregunta:

  1. algún pedazo de código en mi gran sistema hace creación de objetos

La mayoría de los carteles supondrán que está diciendo que está trabajando en una interfaz, si fuera así tendríamos que ver si le entregan el objeto completo o uno a la vez.

Si ya no necesita un objeto, puede asignarle un valor nulo al objeto, pero si lo hace incorrectamente, se generará una excepción de puntero nulo. Apuesto a que puedes lograr un mejor trabajo si usas NIO

Cada vez que usted, yo o cualquier otra persona recibamos: ” Por favor, lo necesito horriblemente. Es un precursor casi universal de la destrucción casi total de aquello sobre lo que está tratando de trabajar … escríbanos un código de muestra pequeño, desinfecte cualquier código real utilizado y muéstranos tu pregunta.

No te frustres A menudo, lo que esto resuelve es que su dba está utilizando un paquete comprado en algún lugar y el diseño original no está ajustado para estructuras de datos masivas.

Eso es muy común.

Si se está quedando sin memoria y obteniendo una OutOfMemoryException , puede intentar boost la cantidad de espacio disponible para Java iniciando su progtwig con java -Xms128m -Xmx512m lugar de solo java . Esto le dará un tamaño de almacenamiento dynamic inicial de 128Mb y un máximo de 512Mb, que es mucho más que el estándar de 32Mb / 128Mb.

(Lo siento, no puedo agregar esto como comentario ya que no tengo suficientes puntos de reputación).

Una vez me entrevisté en una empresa de procesamiento de imágenes para un trabajo en Java (aunque no tenía mucha / mucha experiencia en Java).

Su historia de dolor que era interesante para mí, era que su progtwig asignaría un ENORME buffer para la imagen. Una vez que terminaron con la imagen y la memoria, la respetarían. Sabiendo que realmente necesitaban recuperar la memoria más temprano que tarde, intentaron utilizar una llamada explícita a Java gc () durante un tiempo de tranquilidad del progtwig. Lamentablemente, gc () es simplemente una sugerencia para el tiempo de ejecución de Java y no tuvo ningún efecto.

Según recuerdo, terminaron teniendo que reciclar la memoria ellos mismos.

FYI

El método llamado System.runFinalizersOnExit (true) garantiza que los métodos del finalizador se invoquen antes de que Java se apague. Sin embargo, este método es intrínsecamente inseguro y ha quedado obsoleto. Una alternativa es agregar “shutdown hooks” con el método Runtime.addShutdownHook.

Masarrat Siddiqui

Hay alguna forma indirecta de forzar el recolector de basura. Solo necesita rellenar montones de objetos temporales hasta el momento en que se ejecutará el recolector de elementos no utilizados. Hice la clase que obliga al recolector de basura de esta manera:

 class GarbageCollectorManager { private static boolean collectionWasForced; private static int refCounter = 0; public GarbageCollectorManager() { refCounter++; } @Override protected void finalize() { try { collectionWasForced = true; refCounter--; super.finalize(); } catch (Throwable ex) { Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex); } } public int forceGarbageCollection() { final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000; int iterationsUntilCollected = 0; collectionWasForced = false; if (refCounter < 2) new GarbageCollectorManager(); while (!collectionWasForced) { iterationsUntilCollected++; int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC]; arr = null; } return iterationsUntilCollected; } } 

Uso:

 GarbageCollectorManager manager = new GarbageCollectorManager(); int iterationsUntilGcExecuted = manager.forceGarbageCollection(); 

No sé cuánto puede ser útil este método, porque llena el montón constantemente, pero si tiene una aplicación de misión crítica que DEBE forzar a GC, cuando esta sea la forma portátil de Java para forzar GC.

Me gustaría agregar algo aquí. Por favor, no que Java se ejecute en la máquina virtual y no en la máquina real. La máquina virtual tiene su propia forma de comunicación con la máquina. Puede variar de un sistema a otro. Ahora cuando llamamos al GC, le pedimos a la Máquina Virtual de Java que llame al Recolector de Basura.

Como el recolector de basura está con la máquina virtual, no podemos obligarlo a realizar una limpieza allí mismo. Por el contrario, ponemos en cola nuestra solicitud con el recolector de basura. Depende de la máquina virtual, después de una hora en particular (esto puede cambiar de un sistema a otro, generalmente cuando la memoria de umbral asignada a la JVM está llena), la máquina real liberará el espacio. :RE

El siguiente código se toma del método assertGC (…). Intenta obligar al recolector de basura no determinista a recolectar.

  List alloc = new ArrayList(); int size = 100000; for (int i = 0; i < 50; i++) { if (ref.get() == null) { // Test succeeded! Week referenced object has been cleared by gc. return; } try { System.gc(); } catch (OutOfMemoryError error) { // OK } try { System.runFinalization(); } catch (OutOfMemoryError error) { // OK } // Approach the jvm maximal allocatable memory threshold try { // Allocates memory. alloc.add(new byte[size]); // The amount of allocated memory is increased for the next iteration. size = (int)(((double)size) * 1.3); } catch (OutOfMemoryError error) { // The amount of allocated memory is decreased for the next iteration. size = size / 2; } try { if (i % 3 == 0) Thread.sleep(321); } catch (InterruptedException t) { // ignore } } // Test failed! // Free resources required for testing alloc = null; // Try to find out who holds the reference. String str = null; try { str = findRefsFromRoot(ref.get(), rootsHint); } catch (Exception e) { throw new AssertionFailedErrorException(e); } catch (OutOfMemoryError err) { // OK } fail(text + ":\n" + str); 

Fuente (agregué algunos comentarios para mayor claridad): Ejemplo de NbTestCase

La mejor (si no única) forma de forzar un GC sería escribir una JVM personalizada. Creo que los Garbage collectors son conectables, por lo que probablemente solo puedas elegir una de las implementaciones disponibles para ajustarla.