Les instances Java 8 Stream doivent-elles toujours être close () 'd?

12

Quoth le Javadoc :

Les flux ont une méthode BaseStream.close () et implémentent AutoCloseable, mais presque toutes les instances de flux n'ont pas besoin d'être fermées après utilisation. Généralement, seuls les flux dont la source est un canal IO (tels que ceux renvoyés par Files.lines (Path, Charset)) devront être fermés. La plupart des flux sont soutenus par des collections, des tableaux ou des fonctions de génération, qui ne nécessitent aucune gestion de ressources spéciale. (Si un flux doit être fermé, il peut être déclaré en tant que ressource dans une instruction try-with-resources.)

"Presque tout" et "généralement" sont vagues - si vous écrivez une bibliothèque et que vous extrayez la source de votre Stream des utilisateurs de ce Stream, alors vous devez toujours vous poser la question - "devrais-je fermer cette?" Les Streams soutenus par IO doivent être fermés car les opérations du terminal n'appellent pas close, donc effectivement je dois toujours me souvenir / documenter d'où vient mon Stream, ou je dois toujours le faire close.

L'option nucléaire, je suppose, serait de ne pas renvoyer les Streams des méthodes ou d'accepter les paramètres de Stream, ce qui a été repris par certaines personnes de l'équipe JDK. Je trouve cela trop limitatif compte tenu de l'utilité pratique des Streams.

Quelles sont vos meilleures pratiques concernant la fermeture de Streams? J'ai cherché en ligne une réponse à cette question de la part de certaines personnes du JDK qui sont généralement actives sur des questions communautaires similaires, mais n'ont rien trouvé de pertinent.

RuslanD
la source
Pas un développeur Java, mais j'utiliserais ces règles: - Si un flux est passé en argument, documentez que l'appelant doit fermer le flux si nécessaire; - Si le flux vous est renvoyé par une fonction, supposez que vous devez le fermer.
Bart van Ingen Schenau

Réponses:

6

Comme vous l'avez dit, en Java, vous devez savoir exactement qui est responsable de la libération de quelle ressource, vous pouvez donc mettre les constructions try-catch-appropriées, try-with-resources ou déléguer cette tâche.

La seule chose sur laquelle vous pouvez compter sur le GC pour nettoyer est une mémoire 100% pure.
S'il peut y avoir d'autres ressources mélangées, la seule chose que vous pouvez raisonnablement faire est simplement de jouer en toute sécurité.

Déduplicateur
la source
Donc , fondamentalement , closeest la seule alternative sûre? Je suppose que la question est de savoir comment ne pas rendre le code trop laid chaque fois qu'un Stream serait pratique à utiliser.
RuslanD
1
Oui, s'il peut y avoir des ressources autres que la mémoire, la seule chose sûre à faire est de supposer qu'il y en a . Pas question, même si Java est très mal adapté aux ressources non GC.
Déduplicateur
Donc, si c'est juste un flux entre deux collections (mémoire pure), la fermeture n'est pas nécessaire?
Amalgovinus
@Amalgovinus correct
Brad Cupit
5

En ce qui concerne les "meilleures pratiques", je pense que c'est une bonne idée d'utiliser une convention de dénomination pour les méthodes qui renvoient des "flux de ressources".

Si un flux doit être close()édité, appelez la méthode d'usine open()ou openStream(). Méthodes d'appel qui construisent des flux éphémères stream(), conformément à la convention établie par le SDK. Mettez toujours javadoc sur la méthode pour alerter le client qu'il doit le close()faire.

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

Je souhaite que les auteurs du SDK n'aient pas choisi de mettre AutoCloseablesur la classe de flux de base. Un ResourceStreamsous-type distinct , qui implémente trivialement AutoCloseable, aurait rendu les différents contrats évidents. Ensuite, vous ne pouviez pas fermer un ordinateur Streamqui n'en avait pas besoin et vous pouviez détecter des erreurs ResourceStreamde gestion potentielles dans les outils d'analyse statique.

Selon les besoins de votre base de code (et votre capacité à appliquer les conventions dans la révision de code), vous pouvez établir vous-même une sous-classe de flux requise. Ou si vous souhaitez créer vos propres outils d'analyse statique, une annotation de méthode qui marque directement les ressources gérées.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Jason Trump
la source