Normalmente, no.
Pero como todas las cosas: depende. El GC en Java en estos días es MUY bueno y todo debería limpiarse muy poco después de que ya no sea accesible. Esto es justo después de dejar un método para variables locales y cuando ya no se hace referencia a una instancia de clase para campos.
Solo necesita anular explícitamente si sabe que, de lo contrario, permanecería referenciado. Por ejemplo, una matriz que se mantiene alrededor. Es posible que desee anular los elementos individuales de la matriz cuando ya no sean necesarios.
Por ejemplo, este código de ArrayList:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
return oldValue;
}
Además, anular explícitamente un objeto no hará que se recopile un objeto antes que si simplemente saliera del alcance de forma natural siempre que no queden referencias.
Ambos:
void foo() {
Object o = new Object();
}
y:
void foo() {
Object o = new Object();
o = null;
}
Son funcionalmente equivalentes.
System.gc()
, se eliminará (siempre que no haya otras referencias que apunten a ese objeto).En mi experiencia, la mayoría de las veces, las personas anulan las referencias por paranoia, no por necesidad. Aquí hay una guía rápida:
Si el objeto A hace referencia al objeto B y ya no necesita esta referencia y el objeto A no es elegible para la recolección de basura, entonces debe anular explícitamente el campo. No es necesario anular un campo si el objeto adjunto está obteniendo la basura recolectada de todos modos. Anular campos en un método dispose () casi siempre es inútil.
No es necesario anular las referencias a objetos creadas en un método. Se borrarán automáticamente una vez que finalice el método. La excepción a esta regla es si está ejecutando un método muy largo o un bucle masivo y necesita asegurarse de que algunas referencias se borren antes del final del método. Nuevamente, estos casos son extremadamente raros.
Yo diría que la gran mayoría de las veces no necesitará anular referencias. Tratar de burlar al recolector de basura es inútil. Terminará con un código ineficiente e ilegible.
fuente
El buen artículo es el horror de la codificación de hoy .
La forma en que GC trabaja es buscando objetos que no tengan punteros, el área de su búsqueda es montón / pila y cualquier otro espacio que tengan. Entonces, si establece una variable en nula, el objeto real ahora no es señalado por nadie y, por lo tanto, podría ser GC.
Pero dado que es posible que el GC no se ejecute en ese instante exacto, es posible que no se esté comprando nada. Pero si su método es bastante largo (en términos de tiempo de ejecución), podría valer la pena, ya que aumentará sus posibilidades de que GC recopile ese objeto.
El problema también puede complicarse con las optimizaciones de código, si nunca usa la variable después de establecerla en nulo, sería una optimización segura eliminar la línea que establece el valor en nulo (una instrucción menos para ejecutar). Por lo tanto, es posible que no obtenga ninguna mejora.
Entonces, en resumen, sí puede ayudar, pero no será determinista .
fuente
Al menos en Java, no es programación vudú en absoluto. Cuando creas un objeto en java usando algo como
Foo bar = new Foo();
haces dos cosas: primero, creas una referencia a un objeto, y segundo, creas el objeto Foo en sí. Siempre que exista esa referencia u otra, el objeto específico no se puede controlar. sin embargo, cuando asigna nulo a esa referencia ...
bar = null ;
y asumiendo que nada más tiene una referencia al objeto, se libera y está disponible para gc la próxima vez que pase el recolector de basura.
fuente
Depende.
En términos generales, si mantiene las referencias a sus objetos, más rápido se recopilarán.
Si su método tarda, digamos, 2 segundos en ejecutarse y ya no necesita un objeto después de un segundo de ejecución del método, tiene sentido borrar cualquier referencia a él. Si GC ve que después de un segundo, su objeto todavía está referenciado, la próxima vez podría verificarlo en un minuto más o menos.
De todos modos, establecer todas las referencias en nulo de forma predeterminada es para mí una optimización prematura y nadie debería hacerlo a menos que en casos raros específicos en los que disminuya considerablemente el consumo de memoria.
fuente
Establecer explícitamente una referencia a nulo en lugar de simplemente dejar que la variable salga del alcance, no ayuda al recolector de basura, a menos que el objeto retenido sea muy grande, donde establecerlo en nulo tan pronto como haya terminado es una buena idea.
Generalmente, establecer referencias a nulo, significa para el LECTOR del código que este objeto está completamente terminado y no debería preocuparse por nada más.
Se puede lograr un efecto similar introduciendo un alcance más estrecho colocando un juego adicional de tirantes
{ int l; { // <- here String bigThing = ....; l = bigThing.length(); } // <- and here }
esto permite que bigThing se recolecte como basura justo después de dejar las llaves anidadas.
fuente
public class JavaMemory { private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6); public void f() { { byte[] data = new byte[dataSize]; //data = null; } byte[] data2 = new byte[dataSize]; } public static void main(String[] args) { JavaMemory jmp = new JavaMemory(); jmp.f(); } }
Lanzamientos del programa anterior
OutOfMemoryError
. Si descomentadata = null;
, elOutOfMemoryError
está resuelto. Siempre es una buena práctica establecer la variable no utilizada en nulafuente
Una vez estaba trabajando en una aplicación de videoconferencia y noté una enorme diferencia en el rendimiento cuando me tomé el tiempo para anular referencias tan pronto como ya no necesitaba el objeto. Esto fue en 2003-2004 y solo puedo imaginar que el GC se ha vuelto aún más inteligente desde entonces. En mi caso, tenía cientos de objetos yendo y viniendo fuera de alcance cada segundo, así que noté el GC cuando se activaba periódicamente. Sin embargo, después de que hice un punto a los objetos nulos, el GC dejó de pausar mi aplicación.
Entonces depende de lo que estés haciendo ...
fuente
Si.
De "El programador pragmático" p.292:
Al establecer una referencia a NULL, reduce el número de punteros al objeto en uno ... (lo que permitirá que el recolector de basura lo elimine)
fuente
Supongo que el OP se refiere a cosas como esta:
private void Blah() { MyObj a; MyObj b; try { a = new MyObj(); b = new MyObj; // do real work } finally { a = null; b = null; } }
En este caso, ¿no los marcaría la VM para GC tan pronto como dejen el alcance de todos modos?
¿O, desde otra perspectiva, establecer explícitamente los elementos en nulos provocaría que obtengan GC antes que lo harían si simplemente salieran del alcance? Si es así, la máquina virtual puede pasar tiempo haciendo GC en el objeto cuando la memoria no es necesaria de todos modos, lo que en realidad causaría un peor rendimiento en el uso de la CPU porque estaría haciendo GC más antes.
fuente
null
influya en absoluto en el comportamiento de GC." Depende "
No sé sobre Java, pero en .net (C #, VB.net ...) generalmente no es necesario asignar un valor nulo cuando ya no necesita un objeto.
Sin embargo, tenga en cuenta que "normalmente no es obligatorio".
Al analizar su código, el compilador .net hace una buena valoración del tiempo de vida de la variable ... para saber con precisión cuándo el objeto ya no se usa. Entonces, si escribe obj = null, en realidad podría parecer que el obj todavía se está usando ... en este caso, es contraproducente asignar un valor nulo.
Hay algunos casos en los que podría resultar útil asignar un valor nulo. Un ejemplo es que tiene un código enorme que se ejecuta durante mucho tiempo o un método que se ejecuta en un hilo diferente, o algún bucle. En tales casos, podría ser útil asignar un valor nulo para que sea fácil para el GC saber que ya no se usa.
No existe una regla estricta para esto. Pasando por el lugar anterior asigna nulos en su código y ejecute un generador de perfiles para ver si ayuda de alguna manera. Lo más probable es que no vea ningún beneficio.
Si está tratando de optimizar el código .net, entonces mi experiencia ha sido que tener mucho cuidado con los métodos Dispose y Finalize es en realidad más beneficioso que preocuparse por los nulos.
Algunas referencias sobre el tema:
http://blogs.msdn.com/csharpfaq/archive/2004/03/26/97229.aspx
http://weblogs.asp.net/pwilson/archive/2004/02/20/77422.aspx
fuente
Incluso si anular la referencia fuera marginalmente más eficiente, ¿valdría la pena la fealdad de tener que salpicar su código con estas horribles anulaciones? Solo serían desorden y oscurecerían el código de intención que los contiene.
Es una base de código poco común que no tiene mejor candidato para la optimización que intentar burlar al recolector de basura (más raros aún son los desarrolladores que logran burlarlo). Lo más probable es que sus esfuerzos se gasten mejor en otro lugar, abandonando ese crujiente analizador Xml o encontrando alguna oportunidad para almacenar en caché el cálculo. Estas optimizaciones serán más fáciles de cuantificar y no requieren que ensucie su código base con ruido.
fuente
En la ejecución futura de su programa, los valores de algunos miembros de datos se usarán para computar una salida visible externa al programa. Otros pueden usarse o no, dependiendo de las entradas futuras (e imposibles de predecir) al programa. Se puede garantizar que no se utilizarán otros miembros de datos. Todos los recursos, incluida la memoria, asignados a los datos no utilizados se desperdician. El trabajo del recolector de basura (GC) es eliminar esa memoria desperdiciada. Sería desastroso para el GC eliminar algo que se necesitaba, por lo que el algoritmo utilizado podría ser conservador, reteniendo más que el mínimo estricto. Podría usar optimizaciones heurísticas para mejorar su velocidad, a costa de retener algunos elementos que en realidad no son necesarios. Hay muchos algoritmos potenciales que podría utilizar el GC. Por lo tanto, es posible que los cambios que realice en su programa, y que no afectan la corrección de su programa, podrían afectar el funcionamiento del GC, ya sea para que se ejecute más rápido para hacer el mismo trabajo o para identificar antes los elementos no utilizados. Entonces, este tipo de cambio, estableciendo una referencia de objeto unusdd a
null
, en teoría no siempre es vudú.¿Es vudú? Según se informa, hay partes del código de la biblioteca de Java que hacen esto. Los escritores de ese código son mucho mejores que los programadores promedio y conocen o cooperan con los programadores que conocen los detalles de las implementaciones del recolector de basura. Por lo que sugiere que es a veces un beneficio.
fuente
Como dijiste, hay optimizaciones, es decir, JVM conoce el lugar cuando la variable se usó por última vez y el objeto al que hace referencia puede ser GCed justo después de este último punto (aún ejecutándose en el alcance actual). Así que anular las referencias en la mayoría de los casos no ayuda a GC.
Pero puede ser útil para evitar el problema del "nepotismo" (o "basura flotante") ( lea más aquí o vea el video ). El problema existe porque el montón se divide en generaciones viejas y jóvenes y se aplican diferentes mecanismos de GC: Minor GC (que es rápido y suele limpiar la generación joven) y Major Gc (que provoca una pausa más prolongada para limpiar Old gen). El "nepotismo" no permite que la basura en la generación joven sea recolectada si se hace referencia a la basura que ya estaba en posesión de una generación anterior.
Para evitar el nepotismo, es una buena idea anular las referencias de un objeto que se supone que debe eliminarse. Puede ver esta técnica aplicada en las clases de JDK: LinkedList y LinkedHashMap
private E unlinkFirst(Node<E> f) { final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC // ... }
fuente