8

We are using Java ByteBuffer for socket communication with a C++ server. We know Java is Big-endian and Socket communication is also Big-endian. So whenever the byte stream received and put into a ByteBuffer by Java, we call getInt() to get the value. No problem, no conversion.

But if somehow we specifically set the ByteBuffer byte order to Little-endian (my co-worker actually did this),

  1. will the Java automatically convert the Big-endian into the Little-endian when the data is put into the ByteBuffer?

  2. Then the getInt() of the Little-endian version will return a right value to you?

I guess the answer to above two questions are yes. But when I try to verify my guessing and try to find how the getInt() works in ByteBuffer, I found it is an abstract method. The only subclass of ByteBuffer is the MappedByteBuffer class which didn't implement the abstract getInt(). So where is the implementation of the getInt() method?

For the sending, because we are using Little-endian ByteBuffer, we need to convert them into a Big-endian bytes before we put onto the socket.

Jonas
  • 121,568
  • 97
  • 310
  • 388
5YrsLaterDBA
  • 33,370
  • 43
  • 136
  • 210
  • I see two implementations of the ByteBuffer in Java 6 that implement getInt(). They are java.nio.DirectByteBuffer and java.nio.HeapByteBuffer. A quick glance at HeapByteBuffer looks like it does handle the byte ordering as you expect. – Joshua Aug 04 '11 at 15:24
  • What do you mean by socket communication? the infra, that is TCP/UDP...etc is big endian, but the data you send depends on how you put it and on the platform. – roni bar yanai Aug 04 '11 at 15:27
  • 1
    You have over 40 questions without an accepted answer. Perhaps you can follow up answers so they can be accepted. – Peter Lawrey Aug 04 '11 at 15:43
  • 'I guess the answer to above two questions are yes.' Hard to see why the facility would be provided otherwise. – user207421 Aug 05 '11 at 06:55

2 Answers2

9

ByteBuffer will automatically use the byte order you specify. (Or Big endian by default)

 ByteBuffer bb =
 // to use big endian
 bb.order(ByteOrder.BIG_ENDIAN);

 // to use little endian
 bb.order(ByteOrder.LITTLE_ENDIAN);

 // use the natural order of the system.
 bb.order(ByteOrder.nativeOrder()); 

Both direct and heap ByteBuffers will re-order bytes as you specifiy.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
3

So where is the implementation of the getInt() method?

ByteBuffer is indeed an abstract class. There are several way in which byte buffers can be created:

In my JDK, these create instances of internal classes HeapByteBuffer and DirectByteBuffer. Their respective getInt functions are as follows:

// HeapByteBuffer

public int getInt() {
    return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
}

public int getInt(int i) {
    return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
}

and

// DirectByteBuffer

private int getInt(long a) {
    if (unaligned) {
        int x = unsafe.getInt(a);
        return (nativeByteOrder ? x : Bits.swap(x));
    }
    return Bits.getInt(a, bigEndian);
}

public int getInt() {
    return getInt(ix(nextGetIndex((1 << 2))));
}

public int getInt(int i) {
    return getInt(ix(checkIndex(i, (1 << 2))));
}

In the above, nativeByteOrder and bigEndian are two boolean members indicating respectively -- and somewhat redundantly -- whether the configured byte order: (a) matches the native byte order; (b) is big endian.

NPE
  • 486,780
  • 108
  • 951
  • 1,012