开发者

ByteBuffer getInt() question

开发者 https://www.devze.com 2023-03-25 17:48 出处:网络
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 Byt

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 proble开发者_JS百科m, 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.


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.


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:

  • allocate;
  • wrap;
  • allocateDirect.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消