Java 直接ByteBuffer

Java 直接ByteBuffer,java,java-native-interface,Java,Java Native Interface,我正在用JNI测试direct ByteBufferjava.nio.ByteBuffer。因此,下面的代码试图: 在Java中将值放入直接ByteBuffer C++中的值更改 获取Java中的值 我在想我到底哪里做错了?C++代码管理从java获取数据,但是C++中的更改没有在java中反映出来。 这就是我在java上所做的: public static void main(String[] args){ ByteBuffer bb = ByteBuffer.allocateDire

我正在用JNI测试direct ByteBufferjava.nio.ByteBuffer。因此,下面的代码试图:

在Java中将值放入直接ByteBuffer C++中的值更改 获取Java中的值 我在想我到底哪里做错了?C++代码管理从java获取数据,但是C++中的更改没有在java中反映出来。 这就是我在java上所做的:

public static void main(String[] args){
    ByteBuffer bb = ByteBuffer.allocateDirect(3);
    byte[] b = {122,121,120};
    System.out.println("1: " + new String(b));
    bb.put(b);

    new JNI.process(bb);

    byte[] c = new byte[3];
    c[0] = bb.get();
    System.out.println("4: " + new String(c));
}
这是我在JNI函数上所做的:

JNIEXPORT void JNICALL Java_MarsJNI_mapreduce
  (JNIEnv *env, jobject thisObj, jobject output){
    char *out = (char*)env->GetDirectBufferAddress(output);
    printf("2: %s\n", out);
    out = "ABC";
    printf("3: %s\n", out);
}
我得到的结果是:

1: zyx
2: zyx
3: ABC
Exception in thread "main" java.nio.BufferUnderflowException
    at java.nio.Buffer.nextGetIndex(Buffer.java:474)
    at java.nio.DirectByteBuffer.get(DirectByteBuffer.java:208)
    at MarsJNI.main(MarsJNI.java:21)

我认为你需要在打电话给bb之前打电话给bb.position0。get

我认为你需要在打电话给bb.get之前打电话给bb.position0。get

第一个问题:见@TedBigham的答案。您也可以使用buf.rewind

第二个问题:只将缓冲区的第一个字节复制到c中,而不是整个缓冲区。做:

byte[] c = new byte[3];
bb.rewind();
bb.put(c);
System.out.println("4: " + new String(c));

第三问题:C++代码做:

char *out = (char*)env->GetDirectBufferAddress(output);
// ...
out = "ABC";
但这里要做的是创建{'A','B','C',0}并分配给它;实际上,您并没有修改缓冲区的内容。你应该做:

memcpy(out, "ABC", 3);
第四个问题:用字节[]创建字符串时,应指定编码:

new String(c, StandardCharsets.UTF_8);

第一个问题:参见@TedBigham的答案。您也可以使用buf.rewind

第二个问题:只将缓冲区的第一个字节复制到c中,而不是整个缓冲区。做:

byte[] c = new byte[3];
bb.rewind();
bb.put(c);
System.out.println("4: " + new String(c));

第三问题:C++代码做:

char *out = (char*)env->GetDirectBufferAddress(output);
// ...
out = "ABC";
但这里要做的是创建{'A','B','C',0}并分配给它;实际上,您并没有修改缓冲区的内容。你应该做:

memcpy(out, "ABC", 3);
第四个问题:用字节[]创建字符串时,应指定编码:

new String(c, StandardCharsets.UTF_8);


是的,这是一个问题;然而,还有一个问题,那就是一个问题;还有另外一个问题,除了@TedBigham提到的问题外,你还有一个问题,就是你的修改永远不会变成原来的版本array@fge你指的是out=ABC;在C++代码中?@特迪格姆,是的,我也怀疑这一点,但是我的C++是很生疏的。我认为他需要做一个strcpyn来代替。@TedBigham那应该是strncpy,但这是问题的本质。从@TedBigham提到的部分来看,你有一个问题,你的修改永远不会变成原始版本array@fge你指的是out=ABC;在C++代码中?@特迪格姆,是的,我也怀疑这一点,但是我的C++是很生疏的。“我想他需要做一个strcpyn来代替。”泰德·比格姆:那可能是strncpy,但这是问题的本质。哇,你从一开始就完全理解我了。谢谢欢迎我还发现了另一个问题。。。不过,这个可能很难处理。我不知道与Java的char等价的C++是什么,也不知道它是如何处理语言环境的。知道等价性有什么帮助吗?我认为,通过JNI,我们不应该担心这个?取决于;您打算操纵文本还是纯字节?如果你操纵文本,是的,这从一开始就应该是一个问题。哇,你从一开始就完全理解我。谢谢欢迎我还发现了另一个问题。。。不过,这个可能很难处理。我不知道与Java的char等价的C++是什么,也不知道它是如何处理语言环境的。知道等价性有什么帮助吗?我认为,通过JNI,我们不应该担心这个?取决于;您打算操纵文本还是纯字节?如果你操纵文本,是的,这从一开始就是一个问题。