¿Deberían las instancias de Java 8 Stream estar siempre cerca () 'd?

12

Quoth el Javadoc :

Las transmisiones tienen un método BaseStream.close () e implementan AutoCloseable, pero casi todas las instancias de transmisiones no necesitan cerrarse después del uso. En general, solo las transmisiones cuya fuente es un canal IO (como las que devuelve Files.lines (Path, Charset)) deberán cerrarse. La mayoría de las transmisiones están respaldadas por colecciones, matrices o funciones generadoras, que no requieren una administración especial de recursos. (Si una secuencia requiere cierre, se puede declarar como un recurso en una declaración de prueba con recursos).

"Casi todos" y "en general" son vagos: si está escribiendo una biblioteca y está abstrayendo la fuente de su Stream de los usuarios de ese Stream, entonces de todos modos siempre tiene que hacerse la pregunta: "¿debería cerrar? ¿esta?" Los Streams respaldados por IO deben cerrarse porque las operaciones de terminal no llaman close, por lo que siempre tengo que recordar / documentar de dónde viene mi Stream, o siempre tengo que closehacerlo.

Supongo que la opción nuclear sería no devolver Streams de los métodos o aceptar los parámetros de Stream, que es un sentimiento que ha sido reflejado por algunas personas en el equipo de JDK. Me parece que es demasiado limitante teniendo en cuenta la utilidad práctica de Streams.

¿Cuáles son sus mejores prácticas para cerrar Streams? Busqué en línea una respuesta a esto de algunas de las personas de JDK que generalmente están activas en preguntas similares de la comunidad, pero no encontraron nada relevante.

RuslanD
fuente
No soy un desarrollador de Java, pero usaría estas reglas: - Si se pasa una secuencia como argumento, documente que la persona que llama debe cerrar la secuencia si es necesario; - Si el flujo se le devuelve desde una función, suponga que necesita cerrarlo.
Bart van Ingen Schenau

Respuestas:

6

Como dijiste, en Java necesitas saber exactamente quién es responsable de liberar qué recurso, para que puedas colocar las construcciones de prueba, capturar, probar con recursos o de alguna manera delegar esa tarea.

Lo único de lo que puede depender el GC para limpiarlo es memoria 100% pura.
Si puede haber otros recursos mezclados, lo único que puede hacer razonablemente es simplemente ir a lo seguro.

Deduplicador
fuente
Entonces, ¿básicamente closees la única alternativa segura? Supongo que la pregunta es cómo no hacer que el código se vea demasiado feo cada vez que un Stream sea útil de usar.
RuslanD
1
Sí, si no podrían ser recursos no memoria, la única cosa segura que hacer es asumir que hay son . No hay forma de evitarlo, a pesar de que Java no es muy adecuado para recursos no GC'd.
Deduplicador
Entonces, si es solo una secuencia entre dos colecciones (memoria pura), ¿no es necesario cerrarla?
Amalgovinus
@Amalgovinus correcto
Brad Cupit
5

En cuanto a las "mejores prácticas", creo que es una buena idea utilizar una convención de nomenclatura para métodos que devuelven "flujos de recursos".

Si se debe editar una secuencia close(), llame al método de fábrica open()o openStream(). Llame a los métodos que construyen secuencias efímeras stream(), siguiendo la convención establecida por el SDK. Siempre ponga javadoc en el método para alertar al cliente de que debe close()hacerlo.

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;
}

Desearía que los autores del SDK no hubieran elegido poner AutoCloseableen la clase de flujo base. Un ResourceStreamsubtipo distinto , que se implementa trivialmente AutoCloseable, habría hecho obvios los diferentes contratos. Entonces no podría cerrar un Streamque no lo necesita, y podría detectar un mal manejo potencial ResourceStreamen las herramientas de análisis estático.

Dependiendo de las necesidades de su base de código (y su capacidad para hacer cumplir las convenciones en la revisión de código), usted mismo podría establecer una subclase de secuencia requerida. O si desea crear sus propias herramientas de análisis estático, una anotación de método que marca los recursos administrados directamente.

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