it-swarm-es.tech

¿Cuándo hace System.gc () algo?

Sé que la recolección de basura está automatizada en Java. Pero entendí que si llama a System.gc() en su código, la JVM puede o no decidir realizar una recolección de basura en ese momento. ¿Cómo funciona esto precisamente? ¿Sobre qué base/parámetros decide exactamente la JVM hacer (o no hacer) un GC cuando ve System.gc()?

¿Hay algunos ejemplos en los cuales es una buena idea poner esto en su código?

108
harry

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

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

56
jodonnell

El único ejemplo que se me ocurre donde tiene sentido llamar a System.gc () es cuando se perfila una aplicación para buscar posibles fugas de memoria. Creo que los perfiladores llaman a este método justo antes de tomar una instantánea de la memoria.

28

No tienes control sobre GC en Java: el VM decide. Nunca me he encontrado con un caso en el que System.gc() sea needed . Ya que una llamada System.gc() simplemente SUGIERE que VM hace una recolección de basura y también hace una recolección de basura COMPLETA (generaciones antiguas y nuevas en un montón multigeneracional), entonces puede causarMÁSciclos de cpu a consumir de lo necesario.

En algunos casos, puede tener sentido sugerirle al VM que haga una recopilación completa AHORA, ya que puede saber que la aplicación estará inactiva durante los próximos minutos antes de que se produzca un levantamiento pesado. Por ejemplo, justo después de la inicialización de una gran cantidad de objetos temporales durante el inicio de la aplicación (es decir, simplemente almacené una TONELADA de información, y sé que no tendré mucha actividad durante aproximadamente un minuto). Piense en un IDE como el inicio de Eclipse: se necesita mucho para inicializar, por lo que quizás inmediatamente después de la inicialización tenga sentido hacer un gc completo en ese momento.

24
DustinB

La especificación del lenguaje Java no garantiza que la JVM iniciará 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 Código fuente de OpenJDK , que es la columna vertebral de Oracle JVM, verá que una llamada a System.gc() inicia un ciclo GC. Si utiliza otra JVM, como J9, debe consultar su documentación para encontrar la respuesta. Por ejemplo, la JVM de Azul tiene un recolector de basura que se ejecuta continuamente, por lo que una llamada a System.gc() no hará nada.

Algunas otras respuestas mencionan el inicio de 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 a partir de su código, ya que desordena la semántica de su aplicación. Su aplicación hace algunas cosas de negocios, la JVM se encarga de la gestión de la memoria. Debe mantener esas preocupaciones separadas (no haga que su aplicación haga algo de administración de memoria, enfóquese en los negocios).

Sin embargo, hay pocos casos en que una llamada a System.gc() podría ser comprensible. Consideremos, por ejemplo, microbenchmarks. Nadie quiere tener un ciclo de GC que 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.

22
Pierre Laporte

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

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

17
David Schlosnagle

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

En cuanto a cuándo emitir una recopilación manual, el único momento en el que puede querer hacer esto es cuando abandona una colección grande que contiene un montón de colecciones más pequeñas, por ejemplo un Map<String,<LinkedList>>, y desea intentar obtener el impacto perfecto. y allí, pero en su mayor parte, no debes preocuparte por eso. El GC sabe mejor que tú, lamentablemente, la mayor parte del tiempo.

10
Patrick

Si usa búferes 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.

8
Peter Lawrey

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

La especificación necesita aclaración: Error # 6668279: (spec) System.gc () debe indicar que no recomendamos el uso y no garantizamos el comportamiento

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

Error # 5025281: Permitir que System.gc () dispare colecciones completas concurrentes (no para detener el mundo)

4
eckes

Garbage Collection es bueno en Java, si estamos ejecutando software codificado en Java en Desktop/laptop/server. Puede llamar a System.gc() o Runtime.getRuntime().gc() en Java.

Solo tenga en cuenta que ninguna de esas llamadas está garantizada para hacer nada. Son solo una sugerencia para que el jvm ejecute el recolector de basura. Depende de 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 tuviera tiempo para eso.

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

2
Naveen

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

2
lwpro2

Hay mucho que decir al tomarse el tiempo para probar las distintas configuraciones 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 con memoria limitada y una cantidad relativamente grande de datos: hay algunos datos grandes que llevan a mi entorno al límite, y aunque pude reducir el uso de la memoria, que en teoría debería funcionar bien, todavía obtendría errores de espacio en el montón - las opciones verbales de GC me mostraron que estaba tratando de recolectar basura, pero fue en vano. En el depurador, podría ejecutar System.gc () y, con toda seguridad, habría "suficiente" memoria disponible ... no mucho más, sino suficiente.

En consecuencia, la única vez que mi aplicación llama a System.gc () es cuando está a punto de ingresar al segmento de código donde se asignarán los buffers grandes 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 300 mb están ocupados 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 procesan son de al menos 100-200 MB a la fuente. Todo es parte de un proceso de conversión automática de datos, por lo que todos los datos existen durante períodos de tiempo relativamente cortos a largo plazo.

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

Dicho todo esto, a pesar de que estoy usando System.gc (), aún continué ajustando los parámetros de la 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 Bloque de tropiezo planteado al 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ía que no funcionara con más frecuencia.

2
Kyune

Normalmente, el VM haría una recolección de basura automáticamente antes de lanzar una excepción OutOfMemoryException, por lo que agregar una llamada explícita no debería ayudar, excepto en que tal vez mueve el impacto de rendimiento a un momento anterior en el tiempo.

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

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

1
Vashek

En breve:

Los parámetros son VM dependientes.

Ejemplo de uso: no puedo pensar en una 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();
1
mataal

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

En general, la ejecución de GC explícita puede causar más daño que beneficio, ya que un gc explícito activará una colección completa, lo que lleva mucho más tiempo a medida que atraviesa cada objeto. Si este gc explícito termina siendo llamado repetidamente, podría fácilmente conducir a una aplicación lenta ya que se gasta mucho tiempo ejecutando GCs completos.

Alternativamente, si va sobre el montón con un analizador de pila 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.

1
zxcv

Si desea saber si se llama a su System.gc(), con la nueva actualización 4 de Java 7 puede recibir una notificación cuando la JVM realice la recolección de basura.

No estoy 100% seguro de que la clase GarbageCollectorMXBean haya sido introducida 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

1
Shervin Asgari

Según Thinking in Java de Bruce Eckel, un caso de uso para explícito System.gc () es cuando desea forzar la finalización, i.n. la llamada a finalizar método.

0
Asterisk

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

0
fleture