Comment diagnostiquer Fichier.supprimer() pour retourner false / trouver unclosed flux?
Je travaille avec une 3ème partie JPEG/EXIF de la manipulation de la bibliothèque (Mediautil) qui me causer quelques maux de tête. Je veux changer une image les données EXIF. Pour ce faire, j'ai besoin d'écrire la version mise à jour d'un fichier temporaire, de supprimer l'original et puis renommez le fichier temp pour le nom d'origine.
Mon problème est que le File.delete()
appel échoue et renvoie false
, sans doute parce que la bibliothèque, toujours ouvert, d'une certaine façon -, mais j'ai fait tout ce que je peux trouver dans l'API pour faire fermer tous les volets. Pire encore: le problème semble être la temporisation à charge, et les tests Unitaires, où il se produit parfois échouer et parfois non, mais le code est pas multithread.
Bizarrement, il y a un appel de la bibliothèque qui supprime le problème - mais il supprime également les infos EXIF miniature, dont je n'ai pas vraiment envie. Et en regardant le code, je ne peux absolument pas voir où il ferme les ruisseaux qui pourraient autrement rester ouvert.
Toutes les idées sur la façon de s'attaquer à ce problème?
Edit:
C'est sur Windows XP, la version 6 de Java. Et une autre chose: j'ai trouvé que si je l'appelle System.gc()
avant d'appeler File.delete()
, il fonctionne, sans doute parce que cela provoque des finalizer. De sorte qu'il semble être un unclosed flux.
Sur quelle plate-forme?
bonne idée, mais la désactivation AV n'est pas de faire une différence.
OriginalL'auteur Michael Borgwardt | 2010-01-24
Vous devez vous connecter pour publier un commentaire.
Je pencherais pour de l'aide avec le débogueur ici. Une fouille rapide par le biais de la
java.io
trucs montre que la seule susceptiblefinalize()
candidat est enFileOutputStream
. Afin de gifler un point d'arrêt dans il y, lancez votre programme, et essayer et obtenir de l'System.gc()
pour déclencherFileOutputStream.finalize()
pour libérer votre flux. Cela devrait vous donner une réponse quant à savoir si ou pas c'est votre problème.Une fois que vous pouvez reproduire, alors vous devez commencer à l'appariement de l'instanciation de
FileOutputStream
instances avec leur finalisation. Un bon débogueur vous donnera interne de la JVM, les identificateurs d'objet pour chaque objet, donc si vous pouvez suivre l'Oid comme ils seront créés, et de suivre lorsqu'ils seront finalisés, nous espérons que vous serez en mesure d'associer la touche d'appel pourfinalize
avec un appel spécifique nouvellenew FileOutputStream
.Pourrait être une longue montée, bien que, selon la complexité de votre application.
OK, j'ai maintenant trouvé la fuite dans la bibliothèque à l'aide de cette méthode.
OriginalL'auteur skaffman
Si vous utilisez un FileOutputStream, clôture, il autorise explicitement la suppression du fichier.
par exemple, au lieu de:
que vous devez faire:
Je vous remercie pour votre commentaire, votre question m'a aidé à trouver la raison pour laquelle certains des fichiers de test n'étaient pas supprimés, mais malheureusement, ne pouvait pas voter. J'ai répondu dans l'espoir qu'il serait utile pour d'autres personnes se cogner dans cette, je peux l'enlever si inapproprié.
OriginalL'auteur nkatsar
Pourquoi ne pas renommer le fichier avant de vous rendre à la bibliothèque pour l'ouvrir? Alors peut-être que l'utilisation de Java Fichier.deleteOnExit() pour supprimer le fichier renommé. Par exemple:
OriginalL'auteur Adrian Pronk
Je pense que vous pourriez avoir identifié le problème réel; c'est à dire que l'API que vous utilisez les fuites de descripteurs de fichiers ouverts par le design.
Puisque c'est une bibliothèque open source que vous utilisez, vous avez accès au code source. Par conséquent, vous devriez être en mesure de confirmer cela, et, si nécessaire, le corriger pour vous-même. Et pour être un bon citoyen, de contribuer à votre fix de retour en envoyant un patch.
"Puis de nouveau, elle sera peut-être le déclenchement d'une GC, qui exécute les finaliseurs..." - c'était ma théorie. Mais il ya quelque chose pour essayer de voir si c'est le cas: l'exécution de votre application avec un ÉNORME tas de sorte que le GC est peu susceptible d'être déclenchée par tas, par l'épuisement.
Puisque vous avez trouvé la fuite, mon dernier commentaire est une sorte de redondant. Mais si vous n'avez pas trouvé la fuite, il aurait aidé ... donc je vais le laisser pour la postérité.
OriginalL'auteur Stephen C