Java garde le verrou sur les fichiers sans raison apparente
En dépit de la fermeture de flux enfin clauses semblent sans cesse de fonctionner dans le nettoyage de problèmes lors de l'utilisation de Java. Fichier.delete() ne parvient pas à supprimer des fichiers, l'Explorateur Windows ne parvient pas trop. Système En Cours D'Exécution.gc() permet parfois mais rien de moins que de mettre fin à la VM contribue de manière cohérente et qui n'est pas une option.
Quelqu'un a d'autres idées que je pourrais essayer? J'utilise la version 1.6 de Java sur Windows XP.
Mise à JOUR: FLAC exemple de code supprimé, le code a fonctionné si je l'isole.
Mise à JOUR:
Plus d'infos, ce qui se passe dans Apache Tomcat, Commons FileUpload est utilisé pour télécharger le fichier et pourrait être le coupable, aussi j'utilise de l'Exécution.exec() pour exécuter la LAME dans un processus séparé pour encoder le fichier, mais cela semble peu probable à cause de ce depuis ProcessExplorer indique clairement que java.exe a un RW verrou sur le fichier et la LAME se termine bien.
Mise à JOUR: je suis en train de travailler avec l'hypothèse qu'il existe un manque close() ou un close() qui n'est pas appelé quelque part dans mon code ou une bibliothèque externe. Je ne peux pas le trouver!
source d'informationauteur Jonas Klemming
Vous devez vous connecter pour publier un commentaire.
Le code que vous avez posté, semble bon, ne devrait pas causer de problèmes que vous décrivez. Je comprends que vous avez posté, juste un morceau de code que vous avez - pouvez-vous essayer d'extraire que cette partie d'un programme distinct, l'exécuter et de voir si le problème se produit toujours?
Ma conjecture est qu'il y a un autre endroit dans le code qui ne
new FileInputStream(path);
et de ne pas fermer le flux de données correctement. Vous pourriez être juste de voir les résultats ici lorsque vous essayez de supprimer le fichier.Je suppose que vous êtes en utilisant jFlac. J'ai téléchargé jFlac 1.3 et essayé votre exemple de code sur un flac fraîchement téléchargé à partir d'internet live music archive. Pour moi, cela a fonctionné. J'ai même surveillé avec ProcessExplorer et vu les descripteurs de fichiers ouverts et puis relâchés. Est votre code de test vraiment aussi simple que ce que vous nous avez donné, ou est-ce une version simplifiée de votre code? Pour moi, une fois close() a été appelée, la poignée a été libéré et le fichier a ensuite été supprimé avec succès.
Essayez de changer votre boucle infinie:
ou si vous voulez garder la boucle, puis le mettre à 1 seconde de sommeil entre les tentatives pour supprimer le fichier. J'ai essayé cela avec JDK6 sur WinXP Pro.
N'oubliez pas de mettre un try/catch autour de votre
close()
et le journal des erreurs si la proximité déclenche une exception.Assurez-vous d'avoir vos appels à proximité, dans le bloc finally est pas dans le bloc try. Si il n'y a pas d'essai/enfin, parce que la méthode lève une exception puis ajouter un try/finally et placez le près de là.
Regarde le Gestionnaire des Tâches de Windows. Pour le Processus d'ajouter les "Poignées" de la colonne (dans le menu Affichage). Regardez pour voir si les poignées de continuer à monter sans jamais tomber.
Utiliser un profiler pour voir si vous avez Stream/Lecteur/enregistreur objets autour de vous que vous ne pensez pas que vous devriez avoir.
EDIT:
Merci de poster le code... pour voir. Une seule chose, c'est votre proximité méthodes ne sont pas garanties d'exécution - la première clôture pourrait jeter et puis, la deuxième ne fonctionne pas.
EDIT 2:
final WavWriter wavWriter = new WavWriter(os);
LACDecoder décodeur = new FLACDecoder(est);
Les deux lignes ci-dessus sera la cause de la strams être conservés dans des variables d'instance, sans doute. Comme un test pour voir si vous pouvez régler le flux des références à null après le décodeur.decode() appel (faire un décodeur.cleanup() la méthode peut-être). Voir si la tenue sur les fermé les cours d'eau est à l'origine du problème.
Aussi, à faire vous vous occupez de l'emballage des ruisseaux passé dans l'au-dessus des constructeurs? Si oui, vous pourriez avoir de la fermeture du flux via les wrappers.
Votre exemple de code devrait fonctionner. En fait, j'ai couru votre il sur la version 1.6 de Java/Vista jflac 1.3 et que le fichier source est supprimé, sans aucune boucle.
Je suppose que dans votre cas, un autre processus est de garder le dossier ouvert, peut-être un bureau de recherche de l'indexeur ou un antivirus. Vous pouvez procexp de trouver le processus qui est en fait la tenue sur le fichier.
N'est pas qu'un vide boucle while?
vous avez:
mettre certains espaces, et vous avez réellement:
votre boucle while n'est pas lié à votre try/finally. si vous essayez d'instruction échoue et que le fichier n'est pas créé, tandis que la boucle ne sera jamais complet, parce que le try/finally ne sera jamais exécuter une deuxième fois.
avez-vous l'intention d'en faire un do{ tout votre code } while (votre déclaration)?
parce que ce n'est pas ce que vous avez là.
EDIT pour préciser:
ma suggestion serait de changer votre boucle while pour avoir plus d'info de pourquoi il ne peut pas supprimer:
car si la suppression échoue une fois, juste que sa va pas plus et plus et plus, bien sûr, sa va accrocher. vous n'êtes pas de modification de l'état du fichier dans la boucle.
Maintenant que vous avez ajouté d'autres informations, comme Tomcat, etc, est-ce un problème d'autorisations? êtes-vous essayer d'écrire dans un fichier que l'utilisateur tomcat est en cours d'exécution en tant que (personne?) vm ne peut pas créer? ou de supprimer un fichier que le serveur tomcat processus ne peut pas les supprimer?
Si process explorer/etc dire que java a un verrou sur le fichier, puis quelque chose a toujours un ruisseau à l'aide. quelqu'un pourrait n'avez pas correctement appelé close() sur tous les ruisseaux sont à l'écriture du fichier?
Si vous êtes hors des indices et des idées: Dans cygwin, cd à votre javaroot et exécuter quelque chose comme:
Il peut apporter un peu de suspects...
Une autre chose à essayer depuis que vous utilisez Tomcat-- dans votre Descripteur de Contexte (généralement Tomcat/conf/Catalina/localhost/your-context.xml), vous pouvez définir
antiResourceLocking=true
qui est conçu pour "éviter le verrouillage de ressource sur Windows". La valeur par défaut (si vous n'avez pas à spécifier) est faux. Vaut la peine d'essayer.