Je suis l'idiot qui fait Java depuis des années et qui a oublié de fermer et qui a causé une erreur.
Lors de la réalisation de tests de charge continue sur un serveur en cours de développement, le comportement de l'application est devenu étrange avec le temps. Il n'y avait aucun problème avec le processeur ou l'utilisation de la mémoire, et la cause restait inconnue, mais si je la laissais pendant une semaine ou deux, l'application mourait avec une erreur du type "Impossible d'ouvrir le fichier plus" dans le journal. .. Après cela, lorsque l'application a vérifié le nombre de descripteurs de fichiers ouverts, il a été confirmé que le nombre maximum de descripteurs de fichiers pouvant être ouverts par processus était atteint.
return Files.list(Paths.get(dirPathStr)).map(path -> path.getFileName().toString())
.collect(Collectors.toSet());
Le code en question est ci-dessus. Une méthode qui renvoie une liste de noms de fichiers dans un répertoire en utilisant l'API Stream, mais le répertoire ouvert par Files.list ()
n'est pas fermé.
Même si j'oublie de fermer, je pense que la mémoire elle-même sera libérée par GC, mais les descripteurs de fichiers ne seront pas publiés, donc le nombre de descripteurs de fichiers continuera à augmenter à chaque exécution.
Au fait, lorsque vous utilisez Eclipse pour l'environnement de développement (classe Scanner, etc.), si vous oubliez de fermer dans l'instance de la classe qui ouvre le fichier, cela vous avertira, mais (à partir d'Eclipse 4.7) le code ci-dessus ne vous avertira pas. Pourquoi……
try (Stream<Path> paths = Files.list(Paths.get(dirPathStr))) {
return paths.map(path -> path.getFileName().toString()).collect(Collectors.toSet());
}
J'ai essayé de le fermer correctement. L'augmentation des descripteurs de fichiers ne se produit plus et l'application fonctionne correctement.
Leçons ci-dessous
Recommended Posts