8

C++ サーバーとのソケット通信に Java ByteBuffer を使用しています。Java はビッグエンディアンであり、ソケット通信もビッグエンディアンです。そのため、バイト ストリームが受信され、Java によって ByteBuffer に入れられるたびに、getInt() を呼び出して値を取得します。問題ありません。変換はありません。

しかし、何らかの方法で ByteBuffer のバイト順をリトルエンディアンに具体的に設定すると (私の同僚が実際にこれを行いました)、

  1. データがByteBufferに入れられると、Javaはビッグエンディアンをリトルエンディアンに自動的に変換しますか?

  2. 次に、リトル エンディアン バージョンの getInt() は正しい値を返しますか?

上記の 2 つの質問に対する答えはイエスだと思います。しかし、推測を検証して、ByteBuffer で getInt() がどのように機能するかを調べようとすると、それが抽象メソッドであることがわかりました。ByteBuffer の唯一のサブクラスは、抽象 getInt() を実装していない MappedByteBuffer クラスです。getInt() メソッドの実装はどこにあるのでしょうか。

送信には、リトルエンディアンの ByteBuffer を使用しているため、ソケットに入れる前にビッグエンディアンのバイトに変換する必要があります。

4

2 に答える 2

9

ByteBuffer は、指定したバイト順を自動的に使用します。(またはデフォルトでビッグエンディアン)

 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()); 

直接およびヒープのどちらの ByteBuffers も、指定したとおりにバイトを並べ替えます。

于 2011-08-04T15:27:29.880 に答える
3

では、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);
}

// 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))));
}

上記では、nativeByteOrderbigEndianは2つのブール値のメンバーであり、構成されたバイト順序が次のようにそれぞれ(および多少冗長に)示されます。(a)ネイティブのバイト順序と一致する。(b)はビッグエンディアンです。

于 2011-08-04T15:29:22.913 に答える