¿Hay alguna forma de liberar memoria en Java, similar a la free()
función de C ? ¿O establecer el objeto en nulo y confiar en GC es la única opción?
java
garbage-collection
Felix
fuente
fuente
Respuestas:
Java usa memoria administrada, por lo que la única forma en que puede asignar memoria es mediante el
new
operador, y la única forma en que puede desasignar la memoria es confiando en el recolector de basura.Este documento técnico de administración de memoria (PDF) puede ayudar a explicar lo que está sucediendo.
También puede llamar
System.gc()
para sugerir que el recolector de basura se ejecute inmediatamente. Sin embargo, Java Runtime toma la decisión final, no su código.De acuerdo con la documentación de Java ,
fuente
System.gc()
completo.Nadie parece haber mencionado explícitamente el establecimiento de referencias a objetos
null
, lo cual es una técnica legítima para "liberar" memoria que quizás desee considerar.Por ejemplo, supongamos que declaró
List<String>
al principio de un método que creció en tamaño para ser muy grande, pero que solo fue necesario hasta la mitad del método. En este punto, podría establecer la referencia de Listanull
para permitir que el recolector de basura pueda reclamar potencialmente este objeto antes de que se complete el método (y la referencia queda fuera de alcance de todos modos).Tenga en cuenta que rara vez uso esta técnica en realidad, pero vale la pena considerarla al tratar con estructuras de datos muy grandes.
fuente
No recomendado.
Editar: escribí la respuesta original en 2009. Ahora es 2015.
Los recolectores de basura han mejorado constantemente en los ~ 20 años que Java ha existido. En este punto, si está llamando manualmente al recolector de basura, es posible que desee considerar otros enfoques:
fuente
* "Personalmente, confío en las variables de anulación como marcador de posición para una eliminación adecuada en el futuro. Por ejemplo, me tomo el tiempo para anular todos los elementos de una matriz antes de eliminar (hacer nula) la matriz en sí".
Esto es innecesario La forma en que funciona el GC de Java es que encuentra objetos que no tienen referencia a ellos, por lo que si tengo un Object x con una referencia (= variable) a que apunta a él, el GC no lo eliminará, porque hay una referencia a ese objeto:
Si nulo a, esto sucede:
Entonces ahora x no tiene una referencia apuntando a él y será eliminado. Lo mismo sucede cuando configuras una referencia a un objeto diferente a x.
Entonces, si tiene una matriz arr que hace referencia a objetos x, y y z y una variable a que hace referencia a la matriz, se ve así:
Si nulo a, esto sucede:
Por lo tanto, el GC considera que arr no tiene un conjunto de referencias y lo elimina, lo que le da esta estructura:
Ahora el GC encuentra x, y y z y también los elimina. Anular cada referencia en la matriz no mejorará nada, solo usará el tiempo y el espacio de la CPU en el código (dicho eso, no dolerá más que eso. El GC aún podrá funcionar de la manera que debería )
fuente
Una razón válida para querer liberar memoria de cualquier programa (java o no) es hacer que haya más memoria disponible para otros programas en el nivel del sistema operativo. Si mi aplicación Java utiliza 250 MB, es posible que desee forzarla a 1 MB y hacer que los 249 MB estén disponibles para otras aplicaciones.
fuente
Para ampliar la respuesta y el comentario de Yiannis Xanthopoulos y Hot Licks (lo siento, ¡no puedo comentar aún!), Puede configurar las opciones de VM como este ejemplo:
En mi jdk 7, esto liberará 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 necesitará ajustar estos parámetros.
Si bien no lo vi enfatizado en el siguiente enlace, tenga en cuenta que algunos recolectores de basura pueden no obedecer estos parámetros y, de forma predeterminada, Java puede elegir uno de estos para usted, en caso de que tenga 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 lanza pequeñas cantidades con la configuración predeterminada. Parece que solo lo hace si ~ 70% del montón no se usa, sin embargo ... no sé si sería más agresivo la liberación si el sistema operativo tuviera poca memoria física.
fuente
He hecho experimentos al respecto.
Es cierto que
System.gc();
solo sugiere ejecutar el recolector de basura.Pero llamar
System.gc();
después de establecer todas las referencias anull
, mejorará el rendimiento y la ocupación de la memoria.fuente
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 tenga que liberar memoria en C, no significa que sea una buena idea tener que hacer esto.
Si cree que realmente tiene un buen caso de uso gratis (), inclúyalo en la pregunta para que podamos ver lo que está tratando de hacer, es muy probable que haya una mejor manera.
fuente
Completamente de javacoffeebreak.com/faq/faq0012.html
fuente
En mi caso, dado que mi código Java está destinado a ser portado a otros idiomas en un futuro próximo (principalmente C ++), al menos quiero pagar el servicio de labio para liberar la memoria correctamente, por lo que ayuda al proceso de portabilidad más adelante.
Personalmente, confío en las variables de anulación como marcador de posición para la eliminación adecuada en el futuro. Por ejemplo, me tomo el tiempo de anular todos los elementos de una matriz antes de eliminar (hacer nula) la matriz en sí.
Pero mi caso es muy particular, y sé que estoy tomando éxitos de rendimiento cuando hago esto.
fuente
* "Por ejemplo, supongamos que declaró una Lista al comienzo de un método que creció en tamaño para ser muy grande, pero que solo se requería hasta la mitad del método. En este punto, podría establecer la referencia de Lista como nula para permitir que el recolector de basura reclame potencialmente este objeto antes de que se complete el método (y la referencia queda fuera de alcance de todos modos) ". * *
Esto es correcto, pero esta solución puede no ser generalizable. Si bien establecer una referencia de objeto List a nulo-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 Lista contiene tipos de referencia, establecer el objeto Lista = nulo no desreferenciará -cualquier- de los tipos de referencia contenidos -en- la lista. En este caso, establecer el objeto Lista = nulo dejará huérfanos 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 sea lo suficientemente inteligente como para determinar que los objetos han quedado huérfanos.
fuente
Althrough java proporciona recolección de basura automática, a veces querrá saber qué tan grande es el objeto y cuánto queda. Memoria libre usando programáticamente
import java.lang;
yRuntime r=Runtime.getRuntime();
para obtener valores de memoria usandomem1=r.freeMemory();
para liberar memoria llame alr.gc();
método yfreeMemory()
fuente
La recomendación de JAVA es asignar a nulo
De https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
fuente