Skip to content

FilterOutputStream - considered harmfull

Java besitzt mit java.io.FilterOutputStream eine Klasse die man als Entwickler extended kann um einen OutputStream zu implementieren der Daten filtert. Dabei implementiert die Basisklasse die unterschiedlichen Varianten von write() sowie flush() und close().

Ich hatte im Rahmen der Vorbereitung für eine Apache Commons VFS 2.1 release geschaut, ob der Code bereits mit Java 8 compiliert werden kann. Es sind noch ein paar Punkte offen, aber was besonders auffiel ist, dass ein Unit-Test fehlschlägt. Nach etwas Analyse (VFS-521) habe ich festgestellt, dass das Problem vom FilterOutputStream in Java 8 herrührt, der ein try-with-resource verwendet um flush() und close() durchzuführen. Wenn dabei beide Methoden die selbe Exception werfen so gibt es beim Hinzufügen der unterdrückten Exception statt der erwarteten IOException eine sehr störende IllegalArgumentException: Self-suppression not permitted.

Wenn man sich den Code älterer Java Implementierungen im Vergleich anschaut, so sieht man allerdings, dass diese noch viel problematischer waren. Denn diese verschlucken bei einem close() potentielle IOExceptions die im davor aufgerufenen flush() aufgetreten sind. Das ältere unsichere Verhalten des FOS ist auch ein "akzeptierter" Bug im JDK: JDK-6335274.

Da der FilteredOutputStream nur verschlimmbessert wurde ist meine Lösung Abstand von dessen close() Methode zu nehmen. Und dies gilt leider auch für den BufferedOutputStream. Hier eine Version ohne besondere Unterstützung für suppressed exceptions.

Mal sehen was auf der openjdk-corelibs-dev liste dazu herauskommt, dort habe ich das Problem mal geschildert. Ein JDK-Bug wurde angelegt, der ist aber noch unbearbeitet.