1

非常に初心者の Java プログラマーとして、私はおそらくそのようなことをいじるべきではありません。ByteBuffer残念ながら、オブジェクトを受け入れて使用しようとするとスローするメソッドを持つライブラリを使用しています。

Exception in thread "main" java.lang.NullPointerException: Unable to retrieve native address from ByteBuffer object

ノンダイレクトバッファを使用しているからでしょうか?

編集:私のコードはあまりありません。私が使用しているライブラリは jNetPcap で、パケットをファイルにダンプしようとしています。私のコードは既存のパケットを取得し、そこから ByteBuffer を抽出します。

byte[] bytes = m_packet.getByteArray(0, m_packet.size());
ByteBuffer buffer = ByteBuffer.wrap(bytes);

次に、ByteBuffer を受け取る jNetPcap のダンプ メソッドを呼び出します。

4

3 に答える 3

1

多くの JNI 呼び出しは、直接 ByteBuffer を想定しています。Oracle Java 6.0 の標準ライブラリでさえ、これを想定しており、ヒープ ByteBuffer を提供すると、データを直接ライブラリとの間でコピーします。あなたの場合、直接ByteBufferにコピーできるbyte []があります。注: 直接 ByteBuffer を作成するとコストがかかるため、可能であればそれらをキャッシュ/リサイクルする必要があります。

// the true size is always a multiple of a page anyway.
static final ByteBuffer buffer = ByteBuffer.allocateDirect(4096); 

// synchronize the buffer if you need to, or use a ThreadLocal buffer as a simple cache.
byte[] bytes = m_packet.getByteArray(0, m_packet.size());
buffer.clear();
buffer.put(bytes);
buffer.flip();
于 2010-12-26T17:45:16.337 に答える
1

提供した情報に基づいて、ネイティブコードが基礎となるメモリ構造にアクセスできるようにしないByteBuffer実装を使用しているようです。ByteBufferの直接メモリにアクセスしようとしていますが、これはおそらくそれを行うべきではないことであり、ByteBufferから派生したクラスがデータを直接保存しないために失敗しています。

これが変更できない重要なコードである場合は、Java 実装を使用して ByteBuffer を作成し、元のデータを一時バッファーにコピーすることをお勧めします。新しいバッファをネイティブ メソッドに渡します。次に、コードをプロファイリングして、パフォーマンスへの影響があるかどうかを確認します。

これを行う方法の例を次に示します。ByteBuffer の実装が何を返すかわからないため、ByteBuffer のインターフェイスが正しく実装されていることを確認してくださいrewind()limit()

このコードは、余分なデータが追加されていないことを示すために、意図的にインデックス 3 に不正にアクセスします。

public static void main(String[] args) {

    // This will be your implementation of ByteBuffer that
    // doesn't allow direct access.
    ByteBuffer originalBuffer = ByteBuffer.wrap(new byte[]{12, 50, 70});


    originalBuffer.rewind();
    byte[] newArray = new byte[originalBuffer.limit()];
    originalBuffer.get(newArray, 0, newArray.length);

    ByteBuffer newBuffer = ByteBuffer.wrap(newArray);

    System.out.println("Limit: " + newBuffer.limit());
    System.out.println("Index 0: " + newBuffer.get(0));
    System.out.println("Index 1: " + newBuffer.get(1));
    System.out.println("Index 2: " + newBuffer.get(2));
    System.out.println("Index 3: " + newBuffer.get(3));
}

出力:

制限: 3

インデックス 0: 12

インデックス 1: 50

インデックス2:70

スレッド「Main」Java.lang.indexOutofboundsecectionの例外

    at java.nio.Buffer.checkIndex(Buffer.java:514)

    at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:121)

    at stackoverflow_4534583.Main.main(Main.java:35)
于 2010-12-26T16:43:22.417 に答える
1

wrap は「直接」バイト バッファを作成しません。通常、ダイレクト バイト バッファーは、メモリ マッピング API を使用した結果として生成されます。あなたが使用している JNI コードを作成した人は、非直接バッファーを許容するコードを作成していない限り、あなたに親切ではありませんでした。

ただし、すべてが失われるわけではありません: http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html#allocateDirect(int )

あなたが必要とすることをします。

于 2010-12-26T17:27:41.047 に答える