¿Es posible forzar la recolección de basura en Java, incluso si es difícil de hacer? Lo sé System.gc();
y Runtime.gc();
solo sugieren hacer GC. ¿Cómo puedo forzar GC?
java
garbage-collection
Robert Columbia
fuente
fuente
Respuestas:
Su mejor opción es llamar, lo
System.gc()
que simplemente es una pista para el recolector de basura que desea que haga una recolección. Sin embargo, no hay forma de forzar una recolección inmediata ya que el recolector de basura no es determinista.fuente
non-deterministic == trouble
GC.Collect()
no recopila. En Javagc()
sí.La biblioteca jlibs tiene una buena clase de utilidad para la recolección de basura . Puede forzar la recolección de basura utilizando un ingenioso truco con objetos WeakReference .
RuntimeUtil.gc () de jlibs:
fuente
PhantomReference
con ayReferenceQueue
luego recibiría una notificación después de la finalización, pero aún antes de la limpieza. Finalmente, incluso si detecta con éxito que se recuperó la memoria para este objeto, todavía significaría muy poco en un GC generacional como HotSpot's. Por lo general, coincidiría con la limpieza de la generación joven.System.gc(); System.gc();
, pero seguramente sería interesante saber si alguna vez funcionó mejor que eso. De hecho, solo imprimir cuántas veces fueSystem.gc()
suficiente. La posibilidad de llegar a 2 es bastante escasa.La mejor (si no solo) forma de forzar un GC sería escribir una JVM personalizada. Creo que los recolectores de basura son conectables, por lo que probablemente podría elegir una de las implementaciones disponibles y ajustarla.
Nota: Esta NO es una respuesta fácil.
fuente
Usando la interfaz Java ™ Virtual Machine Tool (JVM TI) , la función
"Obligará a la VM a realizar una recolección de basura". JVM TI es parte de la arquitectura Java Debugger Architecture (JPDA) .
fuente
SÍ , es casi posible forzarlo, debe llamar a los métodos en el mismo orden y al mismo tiempo estos son:
incluso si es solo un objeto para limpiar el uso de estos dos métodos al mismo tiempo, obligue al recolector de basura a usar el
finalise()
método de objeto inalcanzable, liberando la memoria asignada y haciendo lo que dice elfinalize()
método.SIN EMBARGO , es una práctica terrible usar el recolector de basura porque su uso podría introducir una sobrecarga 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, 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 hay una reasignación del objeto, si esto sucede, el objeto se mantendrá vivo y tendrá una resurrección que es técnicamente posible.
fuente
gc()
es solo una pista para ejecutar una recolección de basura.runFinalizers()
solo ejecuta finalizadores en objetos "que han sido descartados". Si el gc no se ejecutó realmente, puede que no haya tales objetos ...Según la documentación de OutOfMemoryError , declara que no se lanzará a menos que la VM no haya podido recuperar la memoria después de una recolección de basura completa. Entonces, si sigue asignando memoria hasta que obtenga el error, ya habrá forzado una recolección de basura completa.
Presumiblemente, la pregunta que realmente quería hacer era "¿cómo puedo reclamar el recuerdo que creo que debería reclamar mediante la recolección de basura?"
fuente
Para solicitar GC manualmente (no desde System.gc ()):
fuente
.gc es un candidato para la eliminación en futuras versiones: un ingeniero de Sun comentó una vez que tal vez menos de veinte personas en el mundo realmente saben cómo usar .gc (). Anoche trabajé durante algunas horas en una central estructura de datos que utiliza datos generados por SecureRandom, en algún lugar justo después de 40,000 objetos, el vm se ralentizaría como si se hubiera quedado sin punteros. Claramente, se estaba ahogando en las tablas de punteros de 16 bits y exhibía un comportamiento clásico de "maquinaria defectuosa".
Intenté -Xms y así sucesivamente, seguí jugando un poco hasta que llegó a unos 57, xxx algo. Luego, correría gc pasando de decir 57.127 a 57.128 después de un gc (), aproximadamente al ritmo de hincha de código en el campamento Easy Money.
Su diseño necesita una revisión fundamental, probablemente un enfoque de ventana deslizante.
fuente
Puede activar un GC desde la línea de comando. Esto es útil para batch / crontab:
Ver :
fuente
La especificación JVM no dice nada específico sobre la recolección de basura. Debido a esto, los vendedores son libres de implementar GC a su manera.
Entonces, esta vaguedad causa incertidumbre en el comportamiento de recolección de basura. Debe 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.
fuente
Si necesita forzar la recolección de basura, tal vez debería considerar cómo administra los recursos. ¿Estás creando objetos grandes que persisten en la memoria? ¿Está creando objetos grandes (p. Ej., Clases de gráficos) que tienen una
Disposable
interfaz y no llamadispose()
cuando termina con ella? ¿Estás declarando algo a nivel de clase que solo necesitas dentro de un solo método?fuente
Sería mejor si describiera la razón por la que necesita la recolección de basura. Si está utilizando SWT, puede disponer recursos como
Image
yFont
para liberar memoria. Por ejemplo:También hay herramientas para determinar recursos no expuestos.
fuente
Si se está quedando sin memoria y está obteniendo una
OutOfMemoryException
, puede intentar aumentar la cantidad de espacio de almacenamiento dinámico disponible para Java iniciando su programa enjava -Xms128m -Xmx512m
lugar de solojava
. Esto le dará un tamaño de almacenamiento dinámico inicial de 128 Mb y un máximo de 512 Mb, que es mucho más que el estándar de 32 Mb / 128 Mb.fuente
java -Xms512M -Xmx1024M
Otra opción es no crear nuevos objetos.
La agrupación de objetos está lejos para reducir la necesidad de GC en Java.
La agrupación de objetos generalmente no va a ser más rápida que la creación de objetos (especialmente para objetos livianos) pero es más rápida que la recolección de basura. Si creó 10,000 objetos y cada objeto tenía 16 bytes. Eso es 160,000 bytes que GC tiene que reclamar. Por otro lado, si no necesita todos los 10,000 al mismo tiempo, puede crear un grupo para reciclar / reutilizar los objetos, lo que elimina la necesidad de construir nuevos objetos y elimina la necesidad de GC objetos antiguos.
Algo como esto (no probado). Y si desea que sea seguro para subprocesos, puede cambiar la LinkedList por una ConcurrentLinkedQueue.
fuente
En OracleJDK 10 con G1 GC, una sola llamada a
System.gc()
hará que GC limpie la colección antigua. No estoy seguro si GC se ejecuta de inmediato. Sin embargo, GC no limpiará la Colección Young, incluso siSystem.gc()
se llama muchas veces en un bucle. Para que GC limpie la Young Collection, debe asignar en un bucle (por ejemplonew byte[1024]
) sin llamarSystem.gc()
. LlamarSystem.gc()
por alguna razón evita que GC limpie la Young Collection.fuente
Esto es correcto, solo un gesto. Tiene casi las respuestas estándar ya dadas por varios carteles. Tomemos esto uno por uno:
Correcto, no existe una jvm real, tal es solo una especificación, un montón de ciencias de la computación que describen un comportamiento deseado ... Hace poco busqué la inicialización de objetos Java a partir de código nativo. Para obtener lo que desea, la única forma es hacer lo que se llama anulación agresiva. Los errores si se hacen mal son tan malos que tenemos que limitarnos al alcance original de la pregunta:
La mayoría de los carteles aquí supondrán que está diciendo que está trabajando para una interfaz, de ser así, tendríamos que ver si le están entregando el objeto completo o un artículo a la vez.
Si ya no necesita un objeto, puede asignar un valor nulo al objeto, pero si se equivoca, se genera una excepción de puntero nulo. Apuesto a que puedes lograr un mejor trabajo si usas NIO
Cada vez que usted o yo o cualquier otra persona recibe: " Por favor, lo necesito horriblemente " . Es un precursor casi universal de la destrucción casi total de lo que está tratando de trabajar ... escríbanos un pequeño código de muestra, desinfectando cualquier código real utilizado y muéstrenos su pregunta.
No te frustres. A menudo, lo que esto resuelve es que su dba está usando un paquete comprado en algún lugar y el diseño original no está ajustado para estructuras de datos masivas.
Eso es muy comun.
fuente
FYI
La llamada al método System.runFinalizersOnExit (true) garantiza que se invoquen los métodos finalizadores antes de que Java se cierre. Sin embargo, este método es inherentemente inseguro y ha quedado en desuso. Una alternativa es agregar "ganchos de apagado" con el método Runtime.addShutdownHook.
Masarrat Siddiqui
fuente
Hay alguna forma indirecta de forzar al recolector de basura. Solo necesita llenar el montón con objetos temporales hasta el punto en que se ejecutará el recolector de basura. He hecho una clase que fuerza al recolector de basura de esta manera:
Uso:
No sé cuánto es útil este método, porque llena el montón constantemente, pero si tiene una aplicación de misión crítica que DEBE forzar GC, cuando esta puede ser la forma portátil de Java de forzar GC.
fuente
Me gustaría agregar algo aquí. Tenga en cuenta que Java no se ejecuta en una máquina virtual y no en una 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.
Dado que el recolector de basura está con la máquina virtual, no podemos obligarlo a hacer una limpieza allí mismo. En lugar de hacer cola nuestra solicitud con el recolector de basura. Depende de la máquina virtual, después de un tiempo 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
fuente
El siguiente código está tomado del método afirmarGC (...). Intenta forzar al recolector de basura no determinista a recolectar.
Fuente (agregué algunos comentarios para mayor claridad): Ejemplo de NbTestCase
fuente
Puede intentar usar
Runtime.getRuntime().gc()
o usar el método de utilidadSystem.gc()
Nota: estos métodos no garantizan GC. Y su alcance debe limitarse a JVM en lugar de manejarlo programáticamente en su aplicación.fuente
Si está utilizando JUnit y Spring, intente agregar esto en cada clase de prueba:
fuente