yugioh recolector recoleccion pagpag ejemplo definicion comida collector basura java garbage-collection

java - recolector - recoleccion de basura definicion



Java: ¿Por qué no se recolecta la basura? (4)

Pregunta rápida sobre la teoría de GCing. Tengo el siguiente método. Se ejecuta, y sale del método. ¿Cómo es que incluso después de que se ejecuta GC, el temporizador sigue existiendo y sigue "TICK"? No creo que todavía haya una referencia al temporizador o al timertask después de que exista este método, por lo que esperaría que el temporizador fuera controlado y causara una excepción. Por favor ayúdame a entender este concepto.

Gracias jbu

private void startTimer() { Timer timer= new Timer(); TimerTask timerTask= new TimerTask() { @Override public void run() { System.out.println("TICK"); } }; timer.scheduleAtFixedRate(timerTask, 0, 500); }


¿Cómo sabes que funcionó el GC? La recolección de basura en general no es una cosa determinista, y definitivamente no está activada por el alcance del método. No es como C ++ donde dejas el alcance de una función y se activan los destructores. Llegará a recopilar esa memoria cuando el GC tenga ganas.


El objeto Timer realidad programa las tareas para que se ejecuten en un subproceso en segundo plano, de modo que el subproceso en segundo plano mantenga una referencia al Timer (y al TimerTask), lo que evita que ambos se recojan.

Aquí está la cita apropiada de los documentos:

Después de que la última referencia en vivo a un objeto del temporizador desaparece y todas las tareas pendientes se han completado, el hilo de ejecución de la tarea del temporizador termina con gracia (y queda sujeto a la recolección de basura). Sin embargo, esto puede tardar un tiempo arbitrario en ocurrir. De forma predeterminada, el subproceso de ejecución de la tarea no se ejecuta como un subproceso de demonio, por lo que es capaz de evitar que una aplicación termine. Si una persona que llama quiere terminar el hilo de ejecución de una tarea del temporizador rápidamente, la persona que llama debe invocar el método de cancelación del temporizador.

Por lo tanto, la condición de que "todas las tareas pendientes han finalizado la ejecución" no se cumple, y el subproceso nunca termina, por lo que Timer / TimerTask nunca es GC''d.


El temporizador no se recolecta como basura porque aún se está ejecutando; algún otro objeto (como el programador de hilos) todavía tiene una referencia a él, que probablemente se creó dentro de scheduleAtFixedRate() .


Porque un temporizador tiene un Timer :

Correspondiente a cada objeto del temporizador es un hilo de fondo único que se utiliza para ejecutar todas las tareas del temporizador, de forma secuencial. Las tareas del temporizador deben completarse rápidamente. Si una tarea de temporizador tarda demasiado tiempo en completarse, "acapara" el hilo de ejecución de la tarea del temporizador. Esto puede, a su vez, retrasar la ejecución de tareas subsiguientes, que pueden "agruparse" y ejecutarse en rápida sucesión cuando (y si) la tarea ofensiva finalmente se completa.

Como se trata de un subproceso en segundo plano, continúa hasta que la JVM se cierra o se detiene.

Actualización: un poco más sobre esto. Un "subproceso en segundo plano" es lo mismo que un subproceso de daemon, denominado por analogía con un proceso de daemon BSD. Si ves los javadocs en Thread , encontrarás:

Marca este hilo como un hilo demonio o un hilo de usuario. La máquina virtual de Java se cierra cuando los únicos subprocesos que se ejecutan son todos los subprocesos del daemon.

Cuando su principal termina, todos los subprocesos del usuario se detienen, dejando solo los subprocesos del daemon. El JVM luego se apaga. Por un buen momento, si es corto, llame a Thread.currentThread().setDaemon(true); de la principal.

Actualización: Ack. Lo tenía casi bien. Tienes que hacer del temporizador un demonio en tiempo de construcción. (¿Esto cambió, o simplemente tuve una falla cerebral?)

De todos modos, aquí está el código de ejemplo:

import java.util.*; class Chatter extends TimerTask { public void run(){ System.err.println("Timer run."); } } public class TryThread { public static void main(String[] argv){ // If argument is true, only runs a few times. Timer t = new Timer(false); t.schedule(new Chatter(), 1L, 1L); return ; } }