I have an InputStream
that's attached to stdout of another process. I sometimes need to log data from the stream, and sometimes don't. Even when I don't care about the output, I still need to read it so that the other process doesn't block due to a full output buffer. I use the following code to selectively log the output:
InputStream is = ...;
boolean report = ...;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
if (report) {
String line = null;
while ((line = br.readLine()) != null) {
Debug.println(line);
}
} else {
while (br.readLine() != null) {
}
}
However, in the second while
loop, FindBugs alerts (RV_DONT_JUST_NULL_CHECK_READLINE) that I'm calling readLine
and only checking whether it's null, not doing anything with the result. Its analysis is correct, but I don't want to do anything with the result in that case. Is there some idiomatic way of consuming and ignoring all data from a stream such that it might not look like a mistake to FindBugs?
You can avoid having to construct String
objects that just get thrown away by using skip
on the InputStream
. (InputStreamReader
and BufferedReader
also have skip
methods, but if you're looking to skip the entire stream, you don't really need the character-decoding features of InputStreamReader
or the line-detection and buffer-management features of BufferedReader
.)
while (is.skip(Long.MAX_VALUE) == Long.MAX_VALUE) {
}
It's unlikely the loop will ever run more than once — you'd need to read 8 exabytes off the stream first — but the loop is there to quell another FindBugs warning (SR_NO_CHECKED) that happens if you call skip
without inspecting the return value.
Using the SuppressWarnings
annotation to silence the compiler is ineffective because it's not the compiler that's worried about the unused return value. The annotation isn't stored in the compiled code, so byte-code analyzers like FindBugs can't see it anyway. Furthermore, none of the warnings that SuppressWarnings
suppresses applies in this situation; in particular, unused
doesn't apply because return values aren't among the things the compiler checks.
Instead of the Java built-in SuppressWarnings
, though, you can try using some other suppression mechanism provided by the static-analysis tool that's generating the warning. In the case of FindBugs, that's the SuppressFBWarnings
annotation.
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
To minimize the scope of the warning suppression, you can isolate the warning-generating code in its own method. For example:
@SuppressFBWarnings("RV_DONT_JUST_NULL_CHECK_READLINE")
private void consumeWholeStream(BufferedReader br) throws IOException {
while (br.readLine() != null) {
}
}
Then you can use that method in the given context:
if (report) {
String line = null;
while ((line = br.readLine()) != null) {
Debug.println(line);
}
} else {
consumeWholeStream(br);
}
The caveat is that this adds the FindBugs annotation jar to your build dependencies. It's not added to the program's run-time dependencies, though.