2011-01-24 22 views
14

Se dice que no podemos forzar el proceso garbage collection en java.
Después de todo, es un hilo de daemon.¿Llamar a System.gc() explícitamente?

Pero todavía a veces, ¿por qué llamamos a la función System.gc(); explícitamente?
¿Vale la pena llamarlo? Cualquier Pro y Con?
Si no es útil en muchas situaciones, ¿por qué este método no está desaprobado de Java?

PS: Explicación con un ejemplo será útil

Respuesta

8

La mejor manera, en mi opinión, de pensar en el método System.gc() es como una "pista" para la VM que debe ejecutar la recolección de basura. Dicho esto, al igual que un gran porcentaje de "optimizaciones" que las personas piensan que están realizando, generalmente es mejor dejar que el sistema se encargue de las cosas por sí mismo. Los sistemas están evolucionando, etc., etc. Todavía hay algunos casos en los que el desarrollador puede saber mejor y el caso de uso es probablemente muy similar al por qué algunos códigos todavía se escriben en ensamblaje (la mayoría de las veces, el compilador es mejor , pero en algunos casos, o con algunos desarrolladores, los humanos pueden escribir códigos más eficientes).

Un ejemplo que he visto en el pasado para justificar su existencia es en el caso de que se asignaran una gran cantidad de objetos y usted, como desarrollador, sepa el momento en que ya no se utilizarán. En ese caso, puede tener más información sobre la utilización de la memoria que el GC (o al menos, antes de que se dé cuenta) y, dado que la cantidad de memoria recuperada será significativa, tiene sentido sugerir que se ejecute.

6

Q: ¿por qué llamamos a la System.gc(); función explícitamente?

A: Porque alguien escribió un código incorrecto.

creo que la mayoría estaría de acuerdo en que no debe llamada System.gc() explícitamente.

Deje que el sistema administre la memoria como se supone que debe hacerlo. Es muy probable que se rompa cualquier código que dependa de eso para el rendimiento. Además, tenga en cuenta que la JVM puede ignorar por completo su solicitud.

Si desea más información, me gustaría sugerir la lectura de las respuestas a:

java - why is it a bad practice to call System.gc?

+0

Sí. Eso es lo que sugirió HFJ. Pero no estaba realmente convencido de su respuesta. –

8

su respuesta es la mitad de su pregunta: ¿merece la pena? No, porque no puedes forzarlo.

Ejecuta el recolector de basura. Llamar a este método sugiere que la máquina virtual Java gasta esfuerzos para reciclar objetos no utilizados a fin de que la memoria que ocupan actualmente esté disponible para su reutilización rápida.

Esto es casi EULA-Inglés para "usted puede intentar pero ambos sabemos el resultado". :)

Además, los servidores de aplicaciones pueden (y con frecuencia lo harán) deshabilitarlo usando la opción de línea de comando -XX:-DisableExplicitGC.

Entonces, ¿cuál es el punto? Bueno, podría haber uno: a algunas aplicaciones les gusta mostrar la cantidad de memoria disponible en el montón, y antes de actualizar la pantalla, podría ser moderadamente útil llamar al System.gc();.

+0

System.gc() es una llamada bastante costosa. "Cuando el control regresa de la llamada al método, la Máquina Virtual Java ha hecho un gran esfuerzo para recuperar espacio de todos los objetos descartados". – RecursiveExceptionException

+1

Esto es como decir que el estilo de vida saludable no vale la pena, ya que no está garantizado que funcione. Si controlas el entorno, puedes asegurarte de que funcione. Hay muchos más usos incorrectos que los usos adecuados de 'System.gc()' por ahí, pero esto no lo hace inútil. – maaartinus

0

¿De qué versión de Java estamos hablando aquí? En 6, nunca lo llamaría explícitamente. Como regla general, el recolector de basura es lo suficientemente bueno para saber cuándo es mejor limpiar los recursos y tiene suficientes opciones de VM configurables. Ciertamente nunca sentí la necesidad de llamarlo en código, y yo diría que a menos que estuvieras haciendo algo realmente extraño (o mostrando el uso de recursos) es mejor no hacerlo. Si siente la necesidad de llamarlo, diría que ha hecho algo malo o incorrecto en otro lado.

Si estamos hablando de trabajar con Java 1.4 o antes, a veces me parece que necesita ayuda. No hay ejemplos a mano (lo siento), pero recuerdo haber necesitado darle una pista para evitar un retraso horrible cuando finalmente decidió entrar en acción. Con el mismo código en 6, el problema desapareció y llamarlo no influyó en nada.

Por supuesto, cuando llama al System.gc(), todo lo que hace es sugerirle a la VM que ahora podría ser un buen momento para ejecutar el recolector de elementos no utilizados. No significa que realmente lo hará, es simplemente una sugerencia de que una implementación de MV perfectamente válida podría ignorar por completo. De hecho hay incluso una opción DisableExplicitGC que significan estas llamadas definitivamente no tendrá efecto (y porciones de código en entornos de producción se ejecuta con esta opción.)

Así que sí, se sigue utilizando en código - pero el la gran mayoría de las veces no es una buena práctica en absoluto.

3

hay algunos casos cuando se llama a System.gc() es útil:

  • Vas a ejecutar algún punto de referencia, por lo que necesita para empezar en un estado bien definido.
  • Estás esperando algo pesado y quieres prepararte lo mejor posible.
  • Tiene varios servidores y desea evitar pausas al programar GC en ellos periódicamente like here.

Puede haber más casos de uso, sin embargo, no es nada que pueda esperar necesitar pronto. La mayoría de las veces es mejor dejar que haga su trabajo a su manera.

+1

No estoy de acuerdo con el segundo: si comienzas a ejecutar una carga "pesada", generalmente la JVM es lo suficientemente buena para realizar esto y GC como corresponda. – berry120

+0

Quiero decir, lo haces * antes * de que comiences la carga pesada, que es algo que la JVM no puede saber de antemano. Es como hacer todos los deberes por adelantado cuando esperas que llegue un día difícil. – maaartinus

+0

@ berry120 puedes vaciar el gen joven (en el punto de acceso del Sol) si estás seguro de que lo enjambres. En general, no se recomienda llamar a GC en un entorno de subprocesos múltiples de ninguna manera excepto solucionar problemas que los desarrolladores de Java dejaron agradecidos. (Hablando nuevamente sobre los búferes mapeados de la memoria zurcida) – bestsss

-1
It is said that we cannot force the garbage collection process in java. 

Esa es una creencia muy popular, que es totalmente errónea.

Varias aplicaciones lo hacen de forma regular y algunas incluso tienen botones brillantes que pueden hacer clic en realmente realizar un GC. En otras palabras: no "sugieren" al GC que les gustaría que se active el GC, pero realmente fuerzan un GC.

Así que esa creencia es a la vez popular e incorrecta. Lo que es menos popular es el conocimiento de cómo en realidad se activa una GC tal, como lo demuestra la respuesta única (y muy vaga) a +6 mis tiempos pregunta upvoted aquí:

Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

+5

No puede "forzar" una JVM genérica para realizar la recolección de elementos no utilizados porque la especificación de JVM no exige realmente un recolector de elementos no utilizados. – ILMTitan

+1

"Cuando el control vuelve de la llamada al método, la Máquina Virtual Java ** ha hecho un gran esfuerzo para recuperar el espacio ** de todos los objetos descartados". No hay motivo para un voto negativo, una JVM que carezca de GC también hace su mejor esfuerzo. – maaartinus

+0

@ILMTitan: Entonces creo que es una buena idea que el 99% de los programas de Java que se ejecutan en máquinas virtuales que permiten instrumentación jvmti y por lo tanto admiten esa llamada documentada;) – SyntaxT3rr0r

2

No es la intención de responder la pregunta, llamar al recolector de basura explícitamente es una mala, mala práctica, sin embargo, algunos códigos en java dependen de la finalización ... e intentan hacer cumplir. Llamarlo también es útil en algunos escenarios de creación de perfiles. Ninguna JVM estándar ignora System.gc(). Claro, puede ser deshabilitado.Sin embargo, si no hay memoria, el recolector de basura maneja las referencias de Java a los recursos externos, podría ser necesario.

Aquí hay un código de java.nio.Bits

static void reserveMemory(long size) { 

    synchronized (Bits.class) { 
     if (!memoryLimitSet && VM.isBooted()) { 
      maxMemory = VM.maxDirectMemory(); 
      memoryLimitSet = true; 
     } 
     if (size <= maxMemory - reservedMemory) { 
      reservedMemory += size; 
      return; 
     } 
    } 

    System.gc(); 
    try { 
     Thread.sleep(100); 
    } catch (InterruptedException x) { 
     // Restore interrupt status 
     Thread.currentThread().interrupt(); 
    } 
    synchronized (Bits.class) { 
     if (reservedMemory + size > maxMemory) 
      throw new OutOfMemoryError("Direct buffer memory"); 
     reservedMemory += size; 
    } 

El sueño es necesario para el finalizado a ejecutar realmente (o intento de pista), limpiadores suelen tener vía rápida en el subproceso finalizador de alta prioridad.

0

Es un anti-pattern to use System.gc() explícitamente, aunque lo usamos para sugerir JVM para barrer la basura, pero depende de la JVM si lo hace o no, además impone algunos criterios que observa cuando se produce System.gc(). Si los criterios siguen, entonces actúa; de otra forma no.

Cuestiones relacionadas