The full picture
byte[] wire = {0x00, 0x00, 0x01, 0x00}; // 256 in big-endian
ByteBuffer.wrap(wire).getInt() // 256 ✅ (Java default: BIG_ENDIAN)
ByteBuffer.wrap(wire).order(ByteOrder.LITTLE_ENDIAN).getInt() // 65536 ❌!
// Reading a little-endian format (most modern formats: Parquet, protobuf
// fixed ints, WAV, x86 core dumps) with the default order = silent garbage
// that often LOOKS plausible — the worst kind of parse bug.
ByteOrder.nativeOrder() // LITTLE_ENDIAN on every machine you'll deploy to
// but 'native' in a wire format = 'undefined contract'. Pick one. Write it down.- Why little-endian won hardware: the byte at offset 0 is the low byte at every width — casts and multi-precision arithmetic address the same bytes; big-endian won wires mostly by IBM/network history (and human-readable hex dumps).
- Where you'll genuinely meet it: hand-rolled binary protocols, reading formats (PNG/JPEG big-endian markers vs BMP/Parquet little), JNI/FFM structs, network code below the HTTP layer (
htons/ntohsin C lore), and cross-language shared memory. Textual formats (JSON) and most serious frameworks (protobuf, Avro) made the choice for you — one honest reason the topic feels obsolete but isn't at the storage/protocol layer. - Debug signature: values that are 'shuffled powers of 256' of the expected (256 ↔ 65536, 1 ↔ 16777216) — recognizing the pattern in a hex dump is the practical skill.
- UTF-8 side note: one of UTF-8's quiet victories is being byte-oriented — no endianness, no BOM ambiguity, unlike UTF-16 (which drags BOMs around precisely because of this question).