Java being Big Endian how does it handle Little Endian CPUs while maintaining performance? Does JVM (OpenJDK, OpenJ9, etc.) do any special optimisations to maintain performance like only selectively being Big Endian in special situation in Little Endian platforms? Is there special endianess handling when accessing ByteBuffers or calling native code or writing to IO or accessing volatile variables? How does Java change the endianess in Little Endian architectures? At what point or operation (load, store, calculation, registers, cache, memory, etc.) is the endianess changed? What kind of performance penalty would this have?
-
1Java doesn't have an endianness per se. Class files have an endianness, but that's just an encoding and it's easy to decode integers from them regardless of endianness; the same holds even for many more esoteric formats. An integer in a register is just stored as that register, and typed arrays don't let you cast them to bytes. – Veedrac Dec 21 '20 at 08:00
1 Answers
Java being Big Endian how does it handle Little Endian CPUs while maintaining performance?
Java is not Big Endian. In the few places in the Java Runtime Library where Endianness is even an issue, the API uses Big Endian, but it is always well-documented, and some of the APIs allow you to specify the Endianness you want.
Does JVM (OpenJDK, OpenJ9, etc.) do any special optimisations to maintain performance like only selectively being Big Endian in special situation in Little Endian platforms?
No, the JVM uses the native Endianness.
Is there special endianess handling when accessing ByteBuffers or calling native code or writing to IO or accessing volatile variables?
Yes, No, Yes, and No.
Since the JVM uses native byte order, there is no handling needed for calling native code or accessing volatile variables. Byte order only matters when (de)serializing to/from bytes, e.g. when accessing ByteBuffers or writing to IO.
How does Java change the endianess in Little Endian architectures?
Same way you would change Endianness anywhere, it swaps the bytes, or read/writes the bytes in the appropriate order.
At what point or operation (load, store, calculation, registers, cache, memory, etc.) is the endianess changed?
It's not, since the JVM uses the native Endianness. Endianness is only applied when the native value is converted to/from bytes. At no other point in time does Endianness matter.
What kind of performance penalty would this have?
None, since it doesn't do anything.

- 154,647
- 11
- 152
- 247
-
Thanks for the answer. This Q&A: [Java's Virtual Machine's Endianness](https://stackoverflow.com/questions/981549/) says the JVM is Big Endian. A comment says the endianess is maintained as a POV. – Suminda Sirinath S. Dharmasena Dec 21 '20 at 09:55
-
1Also [The Java Virtual Machine Specification, Java SE 15 Edition, Section 2.11](https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-2.html#jvms-2.11) says: `The number and size of the operands are determined by the opcode. If an operand is more than one byte in size, then it is stored in big-endian order - high-order byte first. For example, an unsigned 16-bit index into the local variables is stored as two unsigned bytes, byte1 and byte2, such that its value is (byte1 << 8) | byte2.` – Suminda Sirinath S. Dharmasena Dec 21 '20 at 09:56
-
Also [The Java Virtual Machine Specification, Java SE 15 Edition, Chapter 4: The class File Format](https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html) says: `A class file consists of a stream of 8-bit bytes. 16-bit and 32-bit quantities are constructed by reading in two and four consecutive 8-bit bytes, respectively. Multibyte data items are always stored in big-endian order, where the high bytes come first. This chapter defines the data types u1, u2, and u4 to represent an unsigned one-, two-, or four-byte quantity, respectively.` – Suminda Sirinath S. Dharmasena Dec 21 '20 at 10:01
-
If data is stored in native order what does the above mean? I am trying to understand this. – Suminda Sirinath S. Dharmasena Dec 21 '20 at 10:02
-
4The *class-file* is always Big-Endian (it had to choose 1 option, because it has to work unaltered on all platforms); but the *JVM* uses the *platform endiannes*, and only needs to perform conversions when reading bytes from sources (such as class-files) that may or may not have different endiannes – tucuxi Dec 21 '20 at 10:18
-
3@SumindaSirinathS.Dharmasena There's a big difference between the ***bytes*** stored in a bytecode file (`.class`), vs. how data is stored in *memory* in a running JVM. All your comments, as well as the accepted answer in the first link you commented, are all about the bytecode file. Your question is about the JVM (the Java Virtual *Machine*), and that is what this answer addresses. – Andreas Dec 21 '20 at 11:13
-
So just to clarify. (1) Byte-Code/Opcodes + Data in Class Files are Big-Endian. (2) Byte-Code/Opcodes in memory are Big-Endian while Data is platform endiannes. (3) IO again is Big-Endian by default with the options to change it in some instances like in Buffers? – Suminda Sirinath S. Dharmasena Dec 21 '20 at 12:15
-
3@SumindaSirinathS.Dharmasena Correct, except: 2) "Byte-Code/Opcodes in memory" is incomplete, since they may be converted to native CPU instructions by JIT, for better performance. Even without JIT, the JVM might store the Byte-Code/Opcodes in a different way from how it's stored in the bytecode file. It's all internal and the JVM can do whatever it wants. – Andreas Dec 21 '20 at 12:28