2009-03-25 12 views
9

En qué situaciones en java es explícita anulación útil. ¿Ayuda de alguna manera al recolector de basura al hacer objetos inalcanzables o algo así? ¿Se considera una buena práctica?anulación explícita

Respuesta

21

En Java es puede ayudar si tiene un método muy antiguo, y la única referencia a un objeto es a través de una variable local. Al establecer esa variable local en nulo cuando ya no la necesita (pero cuando el método continuará ejecutándose durante un largo tiempo) puede ayudar al GC. (En C# esto rara vez es útil ya que el GC tiene en cuenta el "último uso posible". Esa optimización puede llegar a Java en algún momento, no sé).

Igualmente si tiene un campo de miembro refiriéndose a un objeto y ya no lo necesita, podría ayudar a GC ajustando el campo en nulo.

En mi experiencia, sin embargo, rara vez es en realidad útil para hacer cualquiera de estas cosas, y hace el código más desordenado. Muy pocos métodos realmente funcionan durante mucho tiempo, y establecer una variable en nulo en realidad no tiene nada que ver con lo que quiere que el método logre. No es una buena práctica hacerlo cuando no es necesario, y si usted necesita , debe ver si la refactorización podría mejorar su diseño en primer lugar. (Es posible que su método o tipo esté haciendo demasiado).

Tenga en cuenta que establecer la variable en nulo es completamente pasiva; no informa al recolector de basura que el objeto puede ser recolectado, simplemente evita que el recolector de basura ver esa referencia como una razón para mantener el objeto vivo la próxima vez que se ejecute (el GC).

9

En general, no es necesario (por supuesto, eso puede depender de la implementación de VM). Sin embargo, si usted tiene algo como esto:

private static final Map<String, String> foo; 

y luego tener elementos en el mapa que ya no es necesario que no serán elegibles para la recolección de basura por lo que se necesita para eliminar de forma explícita. Hay muchos casos como este (los oyentes de eventos son otra área con la que esto puede suceder).

Pero hacer algo como esto:

void foo() 
{ 
    Object o; 

    // use o 

    o = null; // don't bother doing this, it isn't going to help 
} 

Editar (olvidó mencionar esto):

Si usted trabaja en él, usted debe encontrar que el 90-95% de las variables que se declaran puede ser hecho final. Una variable final no puede cambiar lo que apunta a (o cuál es su valor para las primitivas). En la mayoría de los casos en que una variable es definitiva, sería un error (error) que reciba un valor diferente mientras el método se está ejecutando.

Si desea poder establecer la variable a nulo después de su uso, no puede ser definitiva, lo que significa que tiene una mayor posibilidad de crear errores en el código.

+0

Buen punto sobre la parte 'final'. +1. Sin embargo, ¡conozco a algunos programadores que parecen considerar agregar como "clutering" su código! Vea esta respuesta: http://stackoverflow.com/questions/132777/do-you-prefix-your-instance-variable-with-this-in-java/135407#135407 – VonC

+0

Hay muchos programadores que piensan esto. Es más o menos un argumento religioso. – Robin

+0

Me gusta todo lo que hace que escribir errores en lugar de código sea más difícil :-) – TofuBeer

3

Si anula un objeto que está a punto de salir de alcance de todos modos cuando se cierra el bloque de método, entonces no hay ningún beneficio en términos de recolección de basura. No es inusual encontrar personas que no entienden esto que trabajan muy duro para establecer un montón de cosas para anular innecesariamente.

5

De "Java efectivo": utilícelo para eliminar las referencias de objetos obsoletas.De lo contrario, puede provocar pérdidas de memoria que pueden ser muy difíciles de depurar.

public Object pop(){ 
    if(size == 0) 
     throw new EmptyStatckException(); 
    Object result = elements[--size]; 
    elements[size] = null; //Eliminate Object reference 
    return result; 
} 
+0

¿Seguro que quiere 'elements [size] == null' DESPUÉS de haber decrementado el tamaño? –

+0

@AndrewLazarus me parece bastante correcto. Imagina una pila de tamaño 1. Almacena un solo elemento en 'elementos [0]'. El elemento se almacena en caché como resultado y la ubicación en la matriz anulada, lo que da como resultado un tamaño de pila de 0. – mtsz

6

Un caso especial lo encontré útil es cuando se tiene un objeto muy grande, y desea reemplazarlo con otro objeto grande. Por ejemplo, mira el siguiente código:

BigObject bigObject = new BigObject(); 
// ... 
bigObject = new BigObject(); // line 3 

Si una instancia de BigObject es tan grande que sólo puede tener uno de esos casos en el montón, la línea 3 fallará con OutOfMemoryError, debido a que la primera instancia no puede ser liberado hasta que se complete la instrucción de asignación en la línea 3, que obviamente es después de que la segunda instancia esté lista.

Ahora, si se establece en null bigObject justo antes de la línea 3:

bigObject = null; 
bigObject = new BigObject(); // line 3 

la primera instancia puede ser liberado cuando la JVM se queda sin pila durante la construcción de la segunda instancia.

+0

Un caso muy raro, pero cierto no obstante. – MBCook

+2

Aunque si esto ocurre, sospecho que tendrías mayores problemas en términos de diseño. – Chii

1

anulación explícita puede ayudar con GC en algunas situaciones excepcionales en los que todos los siguientes son verdaderas:

  • La variable es la única (no débil) referencia al objeto
  • Puede garantía que ya no será necesario el objeto
  • la variable estancia en alcance durante un período prolongado de tiempo (por ejemplo, es un campo de una instancia de objeto de larga vida)
  • El compilador no es capaz de probar que el objeto ya no se usa, pero que son capaces de garantizar esto, sin embargo su análisis lógico superior del código :-)

En la práctica esto es bastante raro en buen código: si el objeto ya no es necesario, normalmente debería declararlo en un ámbito más estrecho de todos modos. Por ejemplo, si solo necesita el objeto durante una única invocación de un método, debe ser una variable local, no un campo en el objeto adjunto.

Una situación en la que la nulidad explícita es realmente útil: si null se utiliza para indicar un estado específico, a veces es necesario y útil establecerlo en un valor nulo. Nulo es un valor útil en sí mismo por un par de razones:

  • cheques nulos son extremadamente rápidos código, de modo condicional que comprueba nula es típicamente más eficiente que muchas alternativas (por ejemplo Object.equals llamada())
  • Obtienes una NullPointerException inmediata si tratas de desreferenciarla. Esto es útil porque es bueno Fail Fast estilo de codificación que le ayudará a detectar errores de lógica.