Hello, buffering with j.i.BufferedInputStream is a handy way to improve performance of IO operations. However in many cases buffering is redundant. Consider this code snippet from Spring Framework:
static ClassReader getClassReader(Resource rsc) throws Exception { try (var is = new BufferedInputStream(rsc.getInputStream())) { return new ClassReader(is); } } Interface Resource has lots of implementations some of them return buffered InputStream, others don't, but all of them get wrapped with BufferedInputStream. Apart from obvious misuses like BufferedInputStream cascade such wrapping is not necessary, e.g. when we read a huge file using FileInputStream.readAllBytes(), in others cases it's harmful e.g. when we read a small (comparing to the default size of buffer in BufferedInputStream) file with readAllBytes() or when we read from ByteArrayInputStream which is kind of buffered one by its nature. I think an instance of InputStream should decide itself whether it requires buffering, so I suggest to add a couple of methods into j.i.InputStream: // subclasses can override this protected boolean needsBuffer() { return true; } public InputStream buffered() { return needsBuffer() ? new BufferedInputStream(this) : this; } this allows subclasses of InputStream to override needsBuffer() to declare buffering redundancy. Let's imagine we've overridden needsBuffer() in BufferedInputStream: public class BufferedInputStream { @Override public boolean needsBuffer() { return true; } } then the code we've mentioned above should be rewritten as static ClassReader getClassReader(Resource rsc) throws Exception { try (var is = rsc.getInputStream().buffered()) { return new ClassReader(is); } } preventing cascade of BufferedInputStreams. There are also cases when the need for buffering depends on the way how we read from InputStream: new FileInputStream(file).buffered().readAllBytes() // buffering is redundant var data = new DataInputStream(new FileInputStream(file).buffered()) for (int i = 0; i < 1000; i++) { data.readInt(); // readInt() does 4 calls to InputStream.read() so buffering is needed } here if FileInputStream.needsBuffer() is overridden and returns false (assuming most of reads from it are bulk) then we won't have buffering for DataInputStream. To avoid this we can also add InputStream.buffered(boolean enforceBuffering) to have manual control. To sum up, my proposal is to add those methods to InputStream: protected static boolean needsBuffer() { return true; } public InputStream buffered() { return buffered(needsBuffer()); } public InputStream buffered(boolean enforceBuffering) { return enforceBuffering ? new BufferedInputStream(this) : this; } What do you think? With best regards, Sergey Tsypanov