Java-Byte Ordering

Byte Ordering

All primitive types are composed of several bytes: a character or a short integer occupies 2 bytes, a 32-bit integer or a floating-point value occupies 4 bytes, and a long integer or a double precision floating-point value occupies 8 bytes. Each value of one of these multibyte types is stored in a sequence of contiguous memory locations. However, the order of these bytes can differ from operating system to operating system.

For example, consider 32-bit integer 623,455,566. This value’s four bytes could be stored in memory (from low address to high address) as 37, 41, 45, 78; this arrangement is known as big endian order (the most-significant byte, the “big” end, is stored at the lowest address). Alternatively, these bytes could be stored as 78, 45, 41, 37; this arrangement is known as little endian order (the least-significant byte, the “little” end, is stored at the lowest address) as illustrated in following figure :

Java provides the java.nio.ByteOrder class to help you deal with byteorder issues when writing/reading multibyte values to/from a multibyte buffer. ByteOrder declares a ByteOrder nativeOrder() method that returns the operating system’s byte order as a ByteOrder instance. Because this instance is one of ByteOrder’s BIG_ENDIAN and LITTLE_ENDIAN constants, and because no other ByteOrder instances can be created, you can compare nativeOrder()’s return value to one of these constants via the == or != operator.

Also, each multibyte class (such as IntBuffer,FloatBuffer) declares a ByteOrder order() method that returns the buffer’s byte order. This method returns ByteOrder.BIG_ENDIAN or ByteOrder.LITTLE_ENDIAN. The ByteOrder value returned from order() can take on a different value based on how the buffer was created. If a multibyte buffer was created by allocation or by wrapping an existing array, the buffer’s byte order is the native order of the underlying operating system. However, if a multibyte buffer was created as a view of a byte buffer, the view buffer’s byte order is that of the byte buffer when the view was created. The view buffer’s byte order cannot be subsequently changed.

ByteBuffer differs from the multibyte classes when it comes to byte order. Its default byte order is always big endian, even when the underlying operating system’s byte order is little endian. ByteBuffer defaults to big endian because Java’s default byte order is also big endian, which lets classfiles and serialized objects store data consistently across Java virtual machines (JVMs). Because this big endian default can impact performance on little endian operating systems, ByteBuffer also declares a order(ByteOrder bo) method to change the byte buffer’s byte order.

Although it may seem unusual to change the byte order of a byte buffer (where only single-byte data items are accessed), this method is useful because ByteBuffer also declares several convenience methods for writing and reading multibyte values (putInt(int value) and getInt(), for example). These convenience methods write these values according to the byte buffer’s current byte order. Furthermore, you can subsequently call ByteBuffer’s LongBuffer asLongBuffer() or another asxBuffer() method to return a view buffer whose order will reflect the byte buffer’s changed byte order.

Program

output

Program Source

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

public class Javaapp {

    public static void main(String[] args) {
        
        ByteBuffer buf = ByteBuffer.allocate(6);
        System.out.println("OS Order         : "+ByteOrder.nativeOrder());
        System.out.println("ByteBuffer Order : "+buf.order());
        buf.put(new byte[]{37,41,45,78});
        buf.flip();
        IntBuffer intbuf = buf.asIntBuffer();
        System.out.println("["+intbuf.position()+" : "+intbuf.get()+"]");
        intbuf.flip();
        buf.order(ByteOrder.LITTLE_ENDIAN);
        intbuf = buf.asIntBuffer();
        System.out.println("["+intbuf.position()+" : "+intbuf.get()+"]");
    }
}

Leave a Comment