Just a note for others: even j.i.ObjectInputStream does peek input (which is essentially read() to peek and reuse peeked byte if already read - for peek and read) : but the class does not say when it will peek and so is impl dependent : luckily, we have not observed it right now; but this can change tomorrow.
The interface contract does not forbid it from reading more than required (unlike what DataInputStream does for example - though even there there is no explicit contract ! just conventional expectation)