metodo estatico definicion java
Recolección de basura en una variable local (3)
Soy un programador de C ++ que ingresa al mundo de Java. Y no puedo deshacerme de la mala sensación de tener que dejar que el recolector de basura de Java haga mi limpieza.
¿Cómo, por ejemplo, se comportará este código en Java?
public void myFunction() {
myObject object = new myObject();
object.doSomething();
}
¿Se eliminará el objeto variable local cuando sale myFunction ()?
¿Tengo que establecer el objeto como nulo antes de salir, o estará fuera del alcance y será eliminado por el GC? O, en el peor, ¿se filtrará como lo haría en C ++?
Saldrá fuera del alcance. En Java, cuando ya nadie apunta a un objeto, será basura recolectada o al menos estará disponible para la recolección de basura. No es necesario configurarlo aquí. En ocasiones, es necesario establecer una referencia de objeto a null si su objeto seguirá vivo en su aplicación, pero una referencia que contenga debe ser recolectada. En este caso, está eligiendo liberar la referencia.
Será basura recolectada en algún momento después de que ya no se use . Creo que en las implementaciones actuales de Java realmente persistirá hasta el final del método, mientras que el recolector de basura en .NET es más agresivo. (No sé si hay garantías, incluso en Java. Normalmente, solo querrá que la variable local persista más allá de su última lectura posible cuando esté depurando).
Pero no, no necesita establecer la variable en nulo, y hacerlo dañaría la legibilidad.
Es poco probable que el objeto recolecte basura inmediatamente después de que el método sale; depende de cuándo se ejecuta el GC ... y, por supuesto, si algo más se aferra a una referencia al objeto, de todos modos puede no ser elegible para la recolección de basura. No olvide que el valor de la variable es solo una referencia, no el objeto en sí. (Puede tomar un tiempo acostumbrarse a venir de C ++).
Encontré este código:
{
final List myTooBigList = new ArrayList();
... overfill the list
}
somethingRunOutOfMemory();
somethingRunOutOfMemory () porque myTooBigList no era GCable, a pesar de que ya no está en el alcance.
Al igual que en C, las variables locales se encuentran en la pila al lado de los marcos. El puntero de la pila reserva tanto espacio como sea necesario para las variables locales en el alcance. La variable local de un bloque se convierte en GCable cuando se reutiliza la pila. Cuando está fuera del alcance, el puntero se mueve hacia atrás tan pronto como lo requieren las nuevas variables locales.
Son GCable después de:
try { } catch : after exit by catch because catch reuses stack
for { } : after exit loop condition because evaluation reuses stack
while { }: after exit loop condition because evaluation reuses stack
{ } followed by any local declaration that reuses stack
No son GCable después de:
try { } finally
try { } catch : after nothing caught
for { } : after break
while { } : after break
do { } while : after loop condition
if { }
{ } not followed by a local declaration
Si quiero que un local sea GCable, escribo:
{
final List myTooBigList = new ArrayList();
... overfill the list
}
Object fake = null;
somethingDoesntRunOutOfMemory();
La afectación de la falsificación mueve el puntero de la pila hacia atrás y hace que myTooBigList sea compatible con GCable. La sorpresa es que (al menos en el jvm estoy probando) tenemos que reutilizar explícitamente la pila. Se esperaría más que las variables locales se puedan poner en GC tan pronto como se salga del bloque, pero supongo que es un compromiso con el rendimiento. Esto complicaría mucho el bytecode.
NOTA: para probar si una variable es GCable, ejecuto GC y luego comparo una WeakReference (mi variable) con nulo.
final WeakReference gctest;
{
final List myTooBigList = new ArrayList();
gctest = new WeakReference(myTooBigList);
... overfill the list
}
Object fake = null;
System.gc();
assert gctest.get() == null;