2009-06-29 16 views
6

Hola, estoy usando una gran cantidad de archivos temporales en Java y mi problema es que no se eliminan.¿Cómo usar la recolección de basura para eliminar archivos?

Sin tener que implementar mi propio manejo de la gestión temporal de archivos (no es difícil, te lo concedo pero soy flojo y tengo tantas cosas que hacer si puedo ahorrar reinventar la rueda todo esto mejor) ¿hay alguna manera de asegúrese de que los archivos temporales en el disco se eliminarán de una manera bastante regular.

1 - usando File tmp = File.createTempFile(), seguro que puedo decir tmp.deleteOnExit() pero si la cosa se ejecuta en un servicio, la única forma en que se cierra es cuando se bloquea (ocurre con poca frecuencia) o cuando el sistema falla (como cuando la unidad está completamente llena de archivos temporales y derriba el clúster ... ¡Uy!)

Idealmente, las instancias creadas se recopilan en algún momento por el recolector de basura, y dado que hay MUCHA el tiempo de inactividad en la aplicación sería simplemente genial si el GC pudiera, bueno, terminar su limpieza y realmente eliminar el archivo en el disco también al eliminar la referencia de la instancia de la memoria.

la única forma que veo ahora es sobrecargar la clase File y agregar un método finalizado ... ¡Si lo hago, también podría hacerlo con mi propio administrador de archivos temporal!

En resumen, ¿puedo usar el Recolector de basura para limpiar los recursos del sistema (es decir, los archivos) también?


Gracias a todos por sus respuestas. Acepté Christoffer porque era lo más simple de implementar y es lo que terminé haciendo.

Supongo que haberme limpiado después de tantos años me ha hecho olvidar la limpieza básica que, sin embargo, tuve que hacer en los buenos días de C++.

+1

Creo que estás confundiendo tus términos. Un recolector de basura es para memoria, no para archivos. –

+0

sin mencionar que si desea que esto se ejecute al salir de la aplicación, deberá colocar algo manual allí, ya que la recolección de basura no se ejecuta en quit/crash (la memoria es desasignada por el SO en ese punto, no el framework) –

+2

Y Java no tiene destructores, por lo que no puede asociar la eliminación con los objetos que se recopilan. – lhahne

Respuesta

2

Seguro que puedes. La pregunta es si realmente quieres :)

De hecho, he encontrado este problema en la naturaleza; como ha notado, limpiar archivos temporales con deleteOnExit() es inútil cuando se ejecuta un servicio en lugar de una aplicación. Descubrí que la solución más estable era reestructurar el flujo del programa de modo que los archivos temporales se crearan por tarea y se eliminen explícitamente cuando ya no los necesiten.

Si lo hace de otra manera, es decir, si el programa no puede concluir si un archivo temporal debe mantenerse o descartarse en algún momento durante la ejecución, es posible que tenga un problema de diseño. Envolver archivos en algún arnés de administrador simplemente pospondrá la solución "real";)

2

Es posible que desee ver en PhantomReference:

objetos de referencia Phantom, que están en cola después de que el colector determina que sus referentes de lo contrario se pueden reutilizar. Las referencias ficticias se utilizan con mayor frecuencia para programar acciones de limpieza premortem de una manera más flexible que la que es posible con el mecanismo de finalización de Java.

+0

sí Las referencias ficticias parecen ser lo que busco aquí donde pueda "engancharme" en el flujo de trabajo del GC e intervenir en algunos objetos. Sin embargo, implementarlo probablemente sea más complejo y menos seguro que simplemente administrarlos manualmente, supongo que enrollaré las mangas y ¡simplemente lo haré! – Newtopian

2

Confiar en un evento para disparar cuando se destruye su clase no será infalible y puede dejar archivos atrasados.

Creo que la forma más sencilla y fiable para lograr la limpieza de los archivos temporales es el siguiente:

  • Escribir un controlador de eventos para cuando el programa se cierra para limpiar los archivos que tenías abiertas durante la sesión actual .
  • Escriba un procedimiento que se ejecutará cuando se inicie el programa, que borrará cualquier archivo temporal en esta carpeta que tenga más de 24 horas.

Con este enfoque no tiene que temer si su programa se cuelga por algún motivo y deja archivos temporales atrás, y tampoco tiene que preocuparse de que el programa borre archivos que todavía están en uso.

+0

ACtualmente, el evento al cierre es gratis para los archivos temporales ... File.deleteOnExit hace justamente eso sin ningún código adicional ... ¡el problema es que la aplicación no se cierra! al menos no en su propio lugar donde este código podría tener efecto. Esto simplemente me deja con el borrado de lotes de vez en cuando. – Newtopian

1

La recolección de basura es el espacio de nombre incorrecto para este tipo de manejo de información.

El siguiente punto debería ser suficiente para manejar archivos temporales.

  1. Debería intentar eliminar el archivo directamente después de que ya no use el archivo. Un bloque de finalización puede manejar esto.

  2. DeleteOnExit debes usar.

  3. Puede crear sus archivos temporales en un directorio especial de temp. Este directorio temporal puede eliminarse cuando se inicia y cierra la aplicación, para asegurarse de que no haya archivos temporales después de que se cierre la aplicación.

+0

1 - finalize para ser útil debe estar en una clase que será reclamada por el GC, por lo tanto, en este caso, tendré que anular la clase File de Java, lo cual soy reacio a hacer. 2- Expresé expresamente que deleteOnExit no funcionará, el programa, en teoría, no sale ... alguna vez 3-sip ... básicamente vuelve a crear mi propio manejo de archivos temporales ... Enseñé del GC, ya que sería natural que también reclame estos recursos, veo que no es tan simple. – Newtopian

0

Bien se podría hacer una envoltura para un archivo que utiliza un finalizer eliminar su archivo cuando el objeto es basura recogida.

Pero los finalizadores no se llaman de ninguna manera predecible, así que realmente no lo recomendaría en absoluto.

+0

sí, eso funcionaría, pero necesitaría extender la clase de archivo + como usted y otros han declarado no es absolutamente confiable. – Newtopian

0

Recolector de basura no es un lugar para liberar este tipo de recurso. Consulte estos dos artículos a continuación sobre cómo liberar recursos en Java http://c2.com/cgi/wiki?ReleasingResourcesInJava Y también los problemas de rendimiento con los finalizadores de Java. Pueden dar alguna idea y entendimiento sobre cómo debería usarse. http://www.enyo.de/fw/notes/java-gc-finalizers.html

+0

buena lectura ... gracias – Newtopian

+0

es un placer – Priyank

1

El recolector de basura no es útil para tales cosas. Está diseñado para la administración de memoria y puede tener muchas desventajas.

  • Su objeto podría ser recogido durante mucho tiempo después de que el archivo ya no esté en uso.
  • Su objeto no está garantizado para ser recogido en absoluto.

Ambas cosas suceden especialmente a menudo, si Java se inicia con un gran tamaño de almacenamiento dinámico, algo que en el lado del servidor no es inusual.

En algún punto de su programa, debe cerrar los flujos en ese archivo (de lo contrario, se comería los archivos del sistema, eso hace que el sistema no se pueda usar, ya lo hice). En el momento en que cierra las transmisiones, también puede eliminar el archivo asociado. Esa es la manera más limpia.

Cuestiones relacionadas