ByteBuffer getInt()问题

5Yr*_*DBA 7 java nio bytebuffer endianness

我们使用Java ByteBuffer与C++服务器进行套接字通信.我们知道Java是Big-endian,而Socket通信也是Big-endian.因此,只要字节流被Java接收并放入ByteBuffer,我们就会调用getInt()来获取值.没问题,没有转换.

但是,如果我们以某种方式将ByteBuffer字节顺序专门设置为Little-endian(我的同事实际上已经这样做了),

  1. 当数据放入ByteBuffer时,Java会自动将Big-endian转换为Little-endian吗?

  2. 那么Little-endian版本的getInt()会给你一个正确的值吗?

我想上面两个问题的答案是肯定的.但是当我尝试验证我的猜测并试图找到getInt()在ByteBuffer中的工作原理时,我发现它是一个抽象方法.ByteBuffer的唯一子类是MappedByteBuffer类,它没有实现抽象的getInt().那么getInt()方法的实现在哪里?

对于发送,因为我们使用Little-endian ByteBuffer,我们需要在放入套接字之前将它们转换为Big-endian字节.

Pet*_*rey 9

ByteBuffer将自动使用您指定的字节顺序.(或默认为Big endian)

 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()); 
Run Code Online (Sandbox Code Playgroud)

直接和堆ByteBuffers都会按照您的指定重新排序字节.


NPE*_*NPE 3

那么getInt()方法的实现在哪里呢?

ByteBuffer确实是一个抽象类。有几种创建字节缓冲区的方法:

在我的 JDK 中,它们创建内部类HeapByteBufferDirectByteBuffer. 其各自的getInt作用如下:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

// 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))));
}
Run Code Online (Sandbox Code Playgroud)

在上面,nativeByteOrderbigEndian是两个布尔值成员,分别指示(有点冗余)配置的字节顺序是否: (a) 与本机字节顺序匹配;(b) 是大端字节序。