5Yr*_*DBA 7 java nio bytebuffer endianness
我们使用Java ByteBuffer与C++服务器进行套接字通信.我们知道Java是Big-endian,而Socket通信也是Big-endian.因此,只要字节流被Java接收并放入ByteBuffer,我们就会调用getInt()来获取值.没问题,没有转换.
但是,如果我们以某种方式将ByteBuffer字节顺序专门设置为Little-endian(我的同事实际上已经这样做了),
当数据放入ByteBuffer时,Java会自动将Big-endian转换为Little-endian吗?
那么Little-endian版本的getInt()会给你一个正确的值吗?
我想上面两个问题的答案是肯定的.但是当我尝试验证我的猜测并试图找到getInt()在ByteBuffer中的工作原理时,我发现它是一个抽象方法.ByteBuffer的唯一子类是MappedByteBuffer类,它没有实现抽象的getInt().那么getInt()方法的实现在哪里?
对于发送,因为我们使用Little-endian ByteBuffer,我们需要在放入套接字之前将它们转换为Big-endian字节.
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都会按照您的指定重新排序字节.
那么getInt()方法的实现在哪里呢?
ByteBuffer确实是一个抽象类。有几种创建字节缓冲区的方法:
在我的 JDK 中,它们创建内部类HeapByteBuffer和DirectByteBuffer. 其各自的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)
在上面,nativeByteOrder和bigEndian是两个布尔值成员,分别指示(有点冗余)配置的字节顺序是否: (a) 与本机字节顺序匹配;(b) 是大端字节序。
| 归档时间: |
|
| 查看次数: |
11711 次 |
| 最近记录: |