¿Existe un destructor para Java?

Resuelto wai asked hace 16 años • 25 respuestas

¿Existe un destructor para Java? Parece que no puedo encontrar ninguna documentación sobre esto. Si no es así, ¿cómo puedo lograr el mismo efecto?

Para hacer mi pregunta más específica, estoy escribiendo una aplicación que maneja datos y la especificación dice que debería haber un botón de "reinicio" que devuelva la aplicación a su estado original recién iniciado. Sin embargo, todos los datos deben estar "activos" a menos que se cierre la aplicación o se presione el botón de reinicio.

Siendo normalmente un programador de C/C++, pensé que esto sería trivial de implementar. (Y por lo tanto planeé implementarlo al final). Estructuré mi programa de manera que todos los objetos "reinicializables" estuvieran en la misma clase para poder destruir todos los objetos "vivos" cuando se presiona un botón de reinicio.

Estaba pensando que si todo lo que hacía era simplemente desreferenciar los datos y esperar a que el recolector de basura los recopile, ¿no habría una pérdida de memoria si mi usuario ingresaba datos repetidamente y presionaba el botón de reinicio? También estaba pensando que, dado que Java es un lenguaje bastante maduro, debería haber una manera de evitar que esto suceda o abordarlo con gracia.

wai avatar Oct 05 '08 20:10 wai
Aceptado

Debido a que Java es un lenguaje de recolección de basura, no se puede predecir cuándo (o incluso si) se destruirá un objeto. Por tanto, no existe un equivalente directo de un destructor.

Hay un método heredado llamado finalize, pero se llama completamente a discreción del recolector de basura. Entonces, para las clases que necesitan ordenar explícitamente, la convención es definir un método close y usar finalize solo para verificar la cordura (es decir, si no se ha llamado a close , hágalo ahora y registre un error).

Hubo una pregunta que generó una discusión profunda sobre finalizar recientemente, por lo que debería proporcionar más profundidad si es necesario...

Garth Gilmour avatar Oct 05 '2008 13:10 Garth Gilmour

Eche un vistazo a la declaración de prueba con recursos . Por ejemplo:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

Aquí se libera en el método el recurso que ya no se necesita BufferedReader.close(). Puede crear su propia clase que la implemente AutoCloseabley la use de manera similar.

Esta declaración es más limitada que finalizeen términos de estructuración del código, pero al mismo tiempo hace que el código sea más sencillo de entender y mantener. Además, no hay garantía de que finalizese llame a un método durante el tiempo de vida de la aplicación.

Vitalii Fedorenko avatar Dec 02 '2011 03:12 Vitalii Fedorenko

No, no hay destructores aquí. La razón es que todos los objetos Java se asignan en montón y se recolectan basura. Sin una desasignación explícita (es decir, el operador de eliminación de C++) no existe una forma sensata de implementar destructores reales.

Java admite finalizadores, pero están destinados a usarse solo como protección para objetos que tienen un identificador de recursos nativos como sockets, identificadores de archivos, identificadores de ventanas, etc. Cuando el recolector de basura recopila un objeto sin un finalizador, simplemente marca la memoria. región como libre y eso es todo. Cuando el objeto tiene un finalizador, primero se copia en una ubicación temporal (recuerde, aquí estamos recogiendo basura), luego se coloca en una cola de espera de finalización y luego un subproceso del Finalizador sondea la cola con una prioridad muy baja. y ejecuta el finalizador.

Cuando se cierra la aplicación, la JVM se detiene sin esperar a que se finalicen los objetos pendientes, por lo que prácticamente no hay garantías de que los finalizadores se ejecuten alguna vez.

ddimitrov avatar Oct 05 '2008 13:10 ddimitrov

Se debe evitar el uso de métodos finalize() . No son un mecanismo confiable para la limpieza de recursos y es posible causar problemas en el recolector de basura si se abusa de ellos.

Si necesita una llamada de desasignación en su objeto, digamos para liberar recursos, use una llamada a un método explícito. Esta convención se puede ver en las API existentes (por ejemplo, Closeable , Graphics.dispose() , Widget.dispose() ) y generalmente se llama a través de try/finally.

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

Los intentos de utilizar un objeto desechado deberían generar una excepción de tiempo de ejecución (consulte IllegalStateException ).


EDITAR:

Estaba pensando, si todo lo que hiciera fuera simplemente desreferenciar los datos y esperar a que el recolector de basura los recopile, ¿no habría una pérdida de memoria si mi usuario ingresara datos repetidamente y presionara el botón de reinicio?

Generalmente, todo lo que necesita hacer es desreferenciar los objetos; al menos, así es como se supone que funciona. Si le preocupa la recolección de basura, consulte Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning (o el documento equivalente para su versión JVM).

McDowell avatar Oct 05 '2008 13:10 McDowell