I have a problem where my program is not ending as expected when an exception is thrown. I have tracked it down to the combination of InputStream and BufferedInputStream swallowing the exceptions. The following code demonstrates the problem:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws IOException {
try (InputStream stream = new BufferedInputStream(new MyStream())) {
int x = stream.read();
while (x != -1) {
System.out.println(x);
x = stream.read();
}
}
}
static class MyStream extends InputStream {
int i = 0;
@Override
public int read() throws IOException {
i = i + 1;
if (i == 5) {
throw new IOException("i == 5");
}
if (i > 10) {
return -1;
}
return i;
}
}
}
This produces the output 1 2 3 4 6 7 8 9 10
If the BufferedInputStream is removed, the exception is thrown when i == 5 as expected.
I tracked it down to the InputStream code. If multiple bytes are read, the InputStream will only propagate an IOException for the first byte, not subsequent bytes. BufferedInputStream changes the read behavior to read multiple bytes at a time and so the IOException is caught by InputStream and discarded.
What is the correct behavior here?
Is it a rule that "Once an IOException, always an IOException" i.e. MyStream needs to remember that it threw an IOException and throw again on any subsequent call?
Other alternatives:
- throw an unchecked exception that will not be caught by the InputStream. I don't think I can throw a different checked exception while extending InputStream
- also override the multi byte read method so it does not catch the IOException. However this seems like it would be vulnerable to the same problem if it was wrapped again by other input streams.
I am grateful for any guidance. At the moment, I think the unchecked exception is my best alternative.