Cómo liberar memoria en Java?


¿Hay una forma de liberar memoria en Java, similar a la función free() de C? ¿O es establecer el objeto en null y confiar en GC la única opción?

Author: Felix, 2009-10-14

13 answers

Java utiliza memoria administrada, por lo que la única forma de asignar memoria es utilizando el operador new, y la única forma de desasignar memoria es confiando en el recolector de basura.

Este documento técnico de gestión de memoria (PDF) puede ayudar a explicar lo que está pasando.

También puede llamar a System.gc() para sugerir que el recolector de basura se ejecute inmediatamente. Sin embargo, el tiempo de ejecución de Java toma la decisión final, no su código.

De acuerdo con el Java documentación,

Llamar al método gc sugiere que la Máquina Virtual Java gasta esfuerzo hacia el reciclaje de objetos no utilizados en para hacer el recuerdo que actualmente ocupar disponible para rápido reutilización. Cuando el control vuelve de la llamada al método, la Máquina Virtual Java ha hecho un mejor esfuerzo para recuperar espacio de todos los objetos desechados.

 87
Author: Daniel Pryden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-15 21:39:04

Nadie parece haber mencionado explícitamente establecer referencias de objetos a null, que es una técnica legítima para "liberar" memoria que puede querer considerar.

Por ejemplo, digamos que declaraste un List<String> al principio de un método que creció en tamaño para ser muy grande, pero solo fue requerido hasta la mitad del método. En este punto, podría establecer la referencia de la lista a null para permitir que el recolector de basura recupere potencialmente este objeto antes de que el método se complete (y referencia cae fuera de alcance de todos modos).

Tenga en cuenta que rara vez uso esta técnica en la realidad, pero vale la pena considerarla cuando se trata de estructuras de datos muy grandes.

 58
Author: Adamski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-14 19:50:13
System.gc(); 

Ejecuta el recolector de basura.

Llamar al método gc sugiere que la Máquina Virtual Java gaste esfuerzo en reciclar objetos no utilizados para que la memoria que ocupan actualmente esté disponible para una reutilización rápida. Cuando el control regresa de la llamada al método, la Máquina Virtual Java ha hecho un mejor esfuerzo para recuperar espacio de todos los objetos descartados.

No se recomienda.

Editar: Escribí la respuesta original en 2009. Estamos en 2015.

Los recolectores de basura han mejorado constantemente en los ~20 años de Java ha existido. En este punto, si está llamando manualmente al recolector de basura, es posible que desee considerar otros enfoques:

  • Si está forzando GC en un número limitado de máquinas, puede valer la pena tener un punto de balanceador de carga lejos de la máquina actual, esperando que termine de servir a los clientes conectados, tiempo de espera después de algún período para colgar conexiones, y luego reinicia la JVM. Esta es una solución terrible, pero si usted está mirando el Sistema.gc (), los reinicios forzados pueden ser un posible recurso provisional.
  • Considere usar un recolector de basura diferente. Por ejemplo, el recopilador G1 (nuevo en los últimos seis años) es un modelo de pausa baja; usa más CPU en general, pero lo mejor es nunca forzar una parada dura en la ejecución. Dado que las CPU de servidor ahora casi todas tienen múltiples núcleos, esta es Una Muy Buena Compensación para tener disponible.
  • Mira tus banderas sintonizan el uso de la memoria. Especialmente en las versiones más recientes de Java, si no tiene tantos objetos en ejecución a largo plazo, considere aumentar el tamaño de newgen en el montón. newgen (young) es donde se asignan nuevos objetos. Para un servidor web, todo lo creado para una solicitud se coloca aquí, y si este espacio es demasiado pequeño, Java pasará más tiempo actualizando los objetos a una memoria de vida más larga, donde son más caros de matar. (Si newgen es un poco demasiado pequeño, vas a pagar por ello.) Por ejemplo, en G1:
    • XX:G1NewSizePercent (por defecto es 5; probablemente no importa.)
    • XX:G1MaxNewSizePercent (el valor predeterminado es 60; probablemente aumente esto.)
  • Considere decirle al recolector de basura que no está de acuerdo con una pausa más larga. Esto causará ejecuciones más frecuentes de GC, para permitir que el sistema mantenga el resto de sus restricciones. En G1:
    • XX: MaxGCPauseMillis (por defecto es 200.)
 22
Author: Dean J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-19 22:46:10

*"Yo personalmente confío en las variables nulling como marcador de posición para futuras eliminaciones adecuadas. Por ejemplo, me tomo el tiempo para anular todos los elementos de una matriz antes de eliminar (hacer nulo) la matriz en sí."

Esto es innecesario. La forma en que funciona Java GC es que encuentra objetos que no tienen referencia a ellos, por lo que si tengo un Objeto x con una referencia (=variable) a que apunta a él, el GC no lo eliminará, porque hay una referencia a ese objeto:

a -> x

Si null a que esto sucede:

a -> null
     x

Así que ahora x no tiene una referencia que apunte a ella y se eliminará. Lo mismo sucede cuando se establece a como referencia a un objeto diferente a x.

Así que si tienes un array arr que hace referencia a objetos x, y y z y una variable a que hace referencia al array se ve así:

a -> arr -> x
         -> y
         -> z

Si null a que esto sucede:

a -> null
     arr -> x
         -> y
         -> z

Así que el GC encuentra que arr no tiene ninguna referencia establecida y lo elimina, lo que le da esto estructura:

a -> null
     x
     y
     z

Ahora el GC encuentra x, y y z y los borra también. Anular cada referencia en la matriz no hará nada mejor, solo consumirá el tiempo de CPU y el espacio en el código (dicho esto, no dañará más que eso. El GC todavía será capaz de realizar la forma en que debería).

 11
Author: Dakkaron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-25 20:28:26

Una razón válida para querer liberar memoria de cualquier programa (java o no ) es hacer más memoria disponible para otros programas a nivel del sistema operativo. Si mi aplicación Java está usando 250MB, es posible que desee forzarla a 1MB y hacer que los 249MB estén disponibles para otras aplicaciones.

 6
Author: Yios,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-27 08:18:27

He hecho experimentos sobre esto.

Es cierto que System.gc(); solo sugiere ejecutar el Recolector de basura.

Pero llamar a System.gc(); después de establecer todas las referencias a null, mejorará el rendimiento y la ocupación de la memoria.

 5
Author: Hemant Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-27 23:27:50

Para extender la respuesta y el comentario de Yiannis Xanthopoulos y Hot Licks (lo siento, ¡todavía no puedo comentar!), puede establecer opciones de VM como este ejemplo:

-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30

En mi jdk 7, esto liberará la memoria de VM no utilizada si más del 30% del montón se libera después de GC cuando la VM está inactiva. Probablemente tendrá que ajustar estos parámetros.

Aunque no lo vi enfatizado en el enlace de abajo, tenga en cuenta que algunos recolectores de basura pueden no obedecer estos parámetros y por defecto java puede elija uno de estos para usted, si sucede que tiene más de un núcleo (de ahí el argumento UseG1GC anterior).

Argumentos de VM

Actualización: Para java 1.8.0_73 He visto que la JVM ocasionalmente libera pequeñas cantidades con la configuración predeterminada. Sin embargo, parece que solo lo hace si ~70% del montón no se usa.. no sé si sería una liberación más agresiva si el sistema operativo tuviera poca memoria física.

 4
Author: nsandersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-12 14:12:34

Si realmente desea asignar y liberar un bloque de memoria, puede hacerlo con ByteBuffers directos. Incluso hay una forma no portátil de liberar la memoria.

Sin embargo, como se ha sugerido, solo porque tengas que liberar memoria en C, no significa que sea una buena idea tener que hacer esto.

Si sientes que realmente tienes un buen caso de uso para free(), por favor inclúyelo en la pregunta para que podamos ver lo que estás intentando hacer, es muy probable que haya una mejor manera.

 3
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-13 20:11:08

Enteramente de javacoffeebreak.com/faq/faq0012.html

Un hilo de baja prioridad se encarga de la recolección de basura automáticamente para el usuario. Durante el tiempo de inactividad, el hilo puede ser invocado, y puede comenzar a liberar memoria previamente asignada a un objeto en Java. Pero no se preocupe , ¡ no eliminará sus objetos en usted!

Cuando no hay referencias a un objeto, se convierte en juego limpio para el recolector de basura. En lugar de llamar a la rutina (como gratis en C++), simplemente asigna todas las referencias al objeto a null, o asigne una nueva clase a la referencia.

Ejemplo :

public static void main(String args[])
{
  // Instantiate a large memory using class
  MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192);

  // Do some work
  for ( .............. )
  {
      // Do some processing on myClass
  }

  // Clear reference to myClass
  myClass = null;

  // Continue processing, safe in the knowledge
  // that the garbage collector will reclaim myClass
}

Si su código está a punto de solicitar una gran cantidad de memoria, puede desea solicitar que el recolector de basura comience a reclamar espacio, en lugar de que permitir que lo haga como un hilo de baja prioridad. Para hacer esto, agregue lo siguiente a su código

System.gc();

El recolector de basura intentará recuperar espacio libre, y tu la aplicación puede continuar ejecutándose, con tanta memoria recuperada como posible (problemas de fragmentación de memoria pueden aplicarse en ciertas plataformas).

 2
Author: Stefan Falk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-20 08:57:42

En mi caso, dado que mi código Java está destinado a ser portado a otros lenguajes en un futuro cercano (Principalmente C++), al menos quiero hablar de liberar memoria adecuadamente para que ayude al proceso de portación más adelante.

Yo personalmente confío en las variables nulling como un marcador de posición para una futura eliminación adecuada. Por ejemplo, me tomo el tiempo para anular todos los elementos de una matriz antes de eliminar (hacer nulo) la matriz en sí.

Pero mi caso es muy particular, y sé que estoy tomando el rendimiento golpea al hacer esto.

 1
Author: Oskuro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-27 11:39:46

* "Por ejemplo, supongamos que ha declarado una Lista al principio de un método que creció en tamaño para ser muy grande, pero sólo se requiere hasta la mitad del método. Usted podría en este punto establecer la List referencia a null para permitir que el recolector de basura potencialmente reclaim this object before the method completes (and the reference cae fuera del alcance de todos modos)." *

Esto es correcto, pero esta solución puede no ser generalizable. Al establecer una referencia de objeto de lista a null-hará que la memoria esté disponible para la recolección de basura, esto solo es cierto para un objeto List de tipos primitivos. Si el objeto List contiene tipos de referencia, establecer el objeto List = null no dereferenciará-ninguno - de los tipos de referencia contenidos en la lista. En este caso, establecer el objeto List = null huérfana los tipos de referencia contenidos cuyos objetos no estarán disponibles para la recolección de basura a menos que el algoritmo de recolección de basura es lo suficientemente inteligente como para determinar que la los objetos han quedado huérfanos.

 1
Author: Gothri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-31 21:11:00

Althrough java proporciona recolección automática de basura a veces querrá saber qué tan grande es el objeto y cuánto queda .Memoria libre usando programáticamente import java.lang; y Runtime r=Runtime.getRuntime(); para obtener valores de memoria usando mem1=r.freeMemory(); para memoria libre llame al método r.gc(); y la llamada freeMemory()

 1
Author: Benjamin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-25 05:18:38

La recomendación de JAVA es asignar a null

De https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html

Asignar explícitamente un valor null a las variables que ya no son necesarias ayuda al recolector de basura a identificar las partes de la memoria que se pueden recuperar de forma segura. Aunque Java proporciona administración de memoria, no evita fugas de memoria o el uso de cantidades excesivas de memoria.

Una aplicación puede inducir fugas de memoria al no liberando referencias de objetos. Hacerlo evita que el recolector de basura de Java reclame esos objetos, y resulta en cantidades crecientes de memoria que se utiliza. La anulación explícita de referencias a variables después de su uso permite al recolector de basura recuperar memoria.

Una forma de detectar fugas de memoria es emplear herramientas de creación de perfiles y tomar instantáneas de memoria después de cada transacción. Una aplicación sin fugas en estado estacionario mostrará una memoria de montón activa constante después de la basura colecciones.

 1
Author: user3869837,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-11 16:24:54