¿Cuándo hace System.gc () algo

Sé que la recolección de basura está automatizada en Java. Pero entendí que si escribes System.gc() en tu código, Java VM puede o no decidir en tiempo de ejecución hacer una recolección de basura en ese punto. ¿Cómo funciona esto exactamente? ¿En qué base / parámetros exactamente el VM decide hacer (o no hacer) un GC cuando ve un System.gc() ? ¿Hay ejemplos, en cuyo caso es una buena idea poner esto en su código?

En la práctica, generalmente decide hacer una recolección de basura. La respuesta varía según muchos factores, como en qué JVM se está ejecutando, en qué modo está y qué algoritmo de recolección de basura está usando.

No dependería de eso en tu código. Si la JVM está a punto de arrojar un OutOfMemoryError, llamar a System.gc () no lo detendrá, porque el recolector de basura intentará liberar todo lo que pueda antes de llegar a ese extremo. La única vez que lo he visto usado en la práctica es en IDEs donde está conectado a un botón que un usuario puede hacer clic, pero incluso allí no es terriblemente útil.

El único ejemplo en el que puedo pensar en dónde tiene sentido llamar a System.gc () es cuando perfila una aplicación para buscar posibles pérdidas de memoria. Creo que los perfiladores llaman a este método justo antes de tomar una instantánea de memoria.

No tienes control sobre GC en Java, la VM decide. Nunca me he encontrado con un caso donde se necesita System.gc() . Como una System.gc() a System.gc() simplemente SUGIERE que la máquina virtual haga una recolección de elementos no utilizados y también una colección COMPLETA de elementos no utilizados (generaciones antiguas y nuevas en un montón multigeneracional), en realidad puede provocar MÁS ciclos de CPU consumidos que necesario.

En algunos casos, puede tener sentido sugerirle al VM que realice una recolección completa AHORA, ya que es posible que sepa que la aplicación estará inactiva durante los próximos minutos antes de que se produzca un movimiento pesado. Por ejemplo, justo después de la inicialización de un montón de objeto temporal durante el inicio de la aplicación (es decir, acabo de almacenar en caché una TONELADA de información, y sé que no obtendré mucha actividad durante un minuto más o menos). Piense en un IDE como el inicio de eclipse; hace mucho para inicializar, por lo que quizás inmediatamente después de la inicialización tenga sentido hacer un gc completo en ese punto.

La Especificación del lenguaje Java no garantiza que la JVM inicie un GC cuando llame a System.gc() . Esta es la razón de esto “puede o no decidir hacer un GC en ese momento”.

Ahora, si observa el código fuente de OpenJDK , que es la columna vertebral de Oracle JVM, verá que una llamada a System.gc() inicia un ciclo de GC. Si usa otra JVM, como J9, debe verificar su documentación para encontrar la respuesta. Por ejemplo, Azul’s JVM tiene un recolector de basura que se ejecuta continuamente, por lo que una llamada a System.gc() no hará nada

Algunas otras respuestas mencionan comenzar un GC en JConsole o VisualVM. Básicamente, estas herramientas hacen una llamada remota a System.gc() .

Por lo general, no desea iniciar un ciclo de recolección de basura desde su código, ya que se equivoca con la semántica de su aplicación. Su aplicación hace algunas cosas de negocios, la JVM se ocupa de la administración de la memoria. Debe mantener esas preocupaciones separadas (no haga que su aplicación haga una gestión de memoria, concéntrese en el negocio).

Sin embargo, hay pocos casos en que una llamada a System.gc() pueda ser comprensible. Considere, por ejemplo, microbenchmarks. Nadie quiere que un ciclo de GC suceda en el medio de un microbenchmark. Por lo tanto, puede activar un ciclo de GC entre cada medición para asegurarse de que cada medición comience con un montón vacío.

System.gc() tener mucho cuidado si llama a System.gc() . Llamarlo puede agregar problemas de rendimiento innecesarios a su aplicación, y no se garantiza que realmente realice una colección. En realidad es posible deshabilitar System.gc() explícito a través del argumento java -XX:+DisableExplicitGC .

Recomiendo leer los documentos disponibles en Java HotSpot Garbage Collection para obtener más información detallada sobre la recolección de basura.

System.gc() es implementado por la VM, y lo que hace es específico de la implementación. El implementador podría simplemente regresar y no hacer nada, por ejemplo.

En cuanto a cuándo emitir un recostackción manual, el único momento en el que puede querer hacer esto es cuando abandona una gran colección que contiene montones de colecciones más pequeñas (por ejemplo Map> ) y desea intenta y toma el golpe de perf entonces, pero en su mayor parte, no deberías preocuparte por eso. El GC lo sabe mejor que usted, por desgracia, la mayoría de las veces.

Si usa memorias intermedias de memoria directa, la JVM no ejecuta el GC por usted, incluso si se está quedando sin memoria directa.

Si llama a ByteBuffer.allocateDirect() y obtiene un OutOfMemoryError, puede encontrar que esta llamada está bien después de activar un GC manualmente.

La mayoría de las JVM iniciarán un GC (según el conmutador -XX: DiableExplicitGC y -XX: + ExplicitGCInvokesConcurrent). Pero la especificación está menos definida para permitir mejores implementaciones más adelante.

La especificación necesita aclaración: Error # 6668279: (especificación) System.gc () debería indicar que no recomendamos el uso y no garantiza el comportamiento

Internamente, el método gc es utilizado por RMI y NIO, y requieren ejecución síncrona, que: esto está actualmente en discusión:

Error # 5025281: Permitir que System.gc () active colecciones completas simultáneas (no pare el mundo)

nunca podemos forzar la recolección de basura. System.gc solo está sugiriendo vm para la recolección de basura, sin embargo, realmente a qué hora se ejecuta el mecanismo, nadie sabe, esto es como lo establecen las especificaciones de JSR.

Hay mucho que decir al tomar el tiempo para probar los diferentes ajustes de recolección de basura, pero como se mencionó anteriormente, generalmente no es útil hacerlo.

Actualmente estoy trabajando en un proyecto que involucra un entorno de memoria limitada y una cantidad relativamente grande de datos: hay algunos datos grandes que llevan mi entorno al límite, y aunque pude reducir el uso de memoria que en teoría debería funcionar bien, aún obtendría errores en el montón de espacio — las opciones verbose GC me mostraron que estaba tratando de recolectar basura, pero fue en vano. En el depurador, podría ejecutar System.gc () y, efectivamente, habría “suficiente” memoria disponible … no mucho más, pero suficiente.

En consecuencia, el único momento en que mi aplicación llama a System.gc () es cuando está a punto de ingresar el segmento de código donde se asignarán grandes búferes necesarios para procesar los datos, y una prueba en la memoria libre disponible indica que no estoy garantizado para tenerlo. En particular, estoy viendo un entorno de 1 gb donde al menos 300mb está ocupado por datos estáticos, y la mayor parte de los datos no estáticos están relacionados con la ejecución, excepto cuando los datos que se están procesando tienen al menos 100-200 MB en la fuente. Todo es parte de un proceso automático de conversión de datos, por lo que todos los datos existen durante períodos relativamente cortos a largo plazo.

Desafortunadamente, aunque la información sobre las diversas opciones para ajustar el recolector de basura está disponible, parece en gran medida un proceso experimental y los detalles de nivel inferior necesarios para comprender cómo manejar estas situaciones específicas no se obtienen fácilmente.

Dicho todo esto, aunque estoy usando System.gc (), seguí sintonizando usando parámetros de línea de comandos y logré mejorar el tiempo de procesamiento general de mi aplicación en una cantidad relativamente significativa, a pesar de no poder superar el tropiezo que plantea trabajar con los bloques de datos más grandes. Dicho esto, System.gc () es una herramienta … una herramienta muy poco confiable, y si no tiene cuidado con la forma en que la usa, deseará que no funcione con la mayor frecuencia.

No puedo pensar en un ejemplo específico cuando es bueno ejecutar un CG explícito.

En general, ejecutar CG explícito en realidad puede causar más daño que beneficio, porque un gc explícito activará una colección completa, lo cual lleva mucho más tiempo a medida que atraviesa cada objeto. Si este explícito gc termina siendo llamado repetidamente, podría llevar fácilmente a una aplicación lenta, ya que se gasta mucho tiempo ejecutando GC completos.

Alternativamente, si pasa el montón con un analizador de stack y sospecha que un componente de la biblioteca está llamando a GC explícitos, puede desactivarlo agregando: gc = -XX: + DisableExplicitGC a los parámetros de JVM.

Normalmente, la VM haría una recolección de basura automáticamente antes de arrojar una excepción OutOfMemoryException, por lo que agregar una llamada explícita no debería ser de ayuda, excepto en que tal vez mueva el golpe de rendimiento a un momento anterior en el tiempo.

Sin embargo, creo que encontré un caso en el que podría ser relevante. Aunque no estoy seguro, ya que aún no he probado si tiene algún efecto:

Cuando hace un mapeo de memoria de un archivo, creo que la llamada a map () arroja una IOException cuando un bloque de memoria lo suficientemente grande no está disponible. Creo que una recolección de basura justo antes del archivo map () podría ayudar a prevenir eso. ¿Qué piensas?

En breve:

Los parámetros dependen de la máquina virtual.

Ejemplo de uso: no se puede pensar en uno para aplicaciones de tiempo de ejecución / producción, pero es útil ejecutarlo para algunos arneses de creación de perfiles, como llamar

 // test run #1 test(); for (int i=0; i<10; i++) { // calling repeatedly to increase chances of a clean-up System.gc(); } // test run #2 test(); 

Si desea saber si se System.gc() su System.gc() , puede con la nueva actualización de Java 7 obtener notificación cuando la JVM realiza la recolección de elementos no utilizados.

No estoy 100% seguro de que la clase GarbageCollectorMXBean se introdujo en la actualización 4 de Java 7, porque no pude encontrarla en las notas de la versión, pero encontré la información en el sitio javaperformancetuning .com

Accroding to Thinking en Java por Bruce Eckel, un caso de uso para la llamada explícita de System.gc () es cuando desea forzar la finalización, es decir, la llamada al método de finalización .

mientras que system.gc funciona, detendrá el mundo: todas las respuestas se detienen para que el recolector de basura pueda escanear cada objeto para comprobar si es necesario eliminarlo. si la aplicación es un proyecto web, todas las solicitudes se detienen hasta que finalice, y esto hará que su proyecto web no pueda funcionar en un monent.

Garbage Collection es buena en Java , si estamos ejecutando software codificado en java en el escritorio / computadora portátil / servidor. Puede llamar a System.gc() o Runtime.getRuntime().gc() en Java .

Solo tenga en cuenta que ninguna de esas llamadas garantiza hacer nada. Son solo una sugerencia para que jvm ejecute el recolector de basura. Es la JVM si ejecuta el GC o no. Entonces, respuesta corta: no sabemos cuándo se ejecuta. Respuesta más larga: JVM ejecutaría gc si tiene tiempo para eso.

Creo que lo mismo aplica para Android. Sin embargo, esto podría ralentizar su sistema.