jbyte* 作为 JNI 中本机 C++ 方法的 ByteBuffer

Posted

技术标签:

【中文标题】jbyte* 作为 JNI 中本机 C++ 方法的 ByteBuffer【英文标题】:jbyte* as ByteBuffer from Native C++ method in JNI 【发布时间】:2012-07-13 21:26:36 【问题描述】:

这里是原生 C++ 方法。

JNIEXPORT jboolean JNICALL Java_xpnp_XpNamedPipe_readBytes
(JNIEnv* pEnv, jclass cls, jlong pipeHandle, jbyteArray readBufferJava, jint bytestoread, jint timeoutMsecs)

    jbyte* readBuffer = NULL;
    try 
        readBuffer = pEnv->GetByteArrayElements(readBufferJava, NULL);
        if (readBuffer == NULL) 
            throw std::bad_alloc();
        
        int retval = XPNP_readBytes ((XPNP_PipeHandle)pipeHandle, (char*)readBuffer, bytestoread, timeoutMsecs);

        std::cout<<"this is what I read: " << readBuffer << "\n";
        std::flush(std::cout);

        return (retval <= 0) ? 0 : retval;
    catch (std::exception& except) 
        // setErrorInfo(except.what());
    
    return 0;

此方法打印从调用XPNP_readBytes 读取的readBuffer 的正确文本,但将全零数组传递给Java!知道为什么会这样吗?我在传递指针或将其转换为 Java 时做错了吗?

这里是 Java 文件中原生 C++ 方法的声明。

private static native boolean readBytes(long pipeHandle, byte[] buffer, int bytesToRead, int timeoutMsecs);

这是我调用本机方法的地方。

boolean b = readBytes(namedPipeHandle, buffer, bytesToRead, timeoutMsecs);
String a = new String(buffer);

我在调用后读到的buffer 全为 0,尽管它在本机代码中打印了正确的文本!

【问题讨论】:

我会考虑使用直接的 ByteBuffer,因为它将地址保存到本机内存块。这避免了将数据复制到 byte[] 的需要,并且如果您需要读取更长的类型,例如 intdouble,效率会更高 哦,我在这里使用的所有byte[] 实际上都是ByteBuffers。我刚刚做了一个toArray()。为简单起见,我只是在帖子中写了byte[]。无论如何感谢您的提示。 基本上((DirectBuffer) byteBuffer).address()是你可以使用的void *的地址。 如果它们是直接缓冲区,请参阅***.com/questions/8000548/… 这个问题及其 cmets 令人困惑。问题并没有简化为最简单的版本。 “我在这里使用的所有byte[] 实际上都是ByteBuffers”......“如果它们是直接缓冲区,那么......”......“不。它们是字节数组。”它是哪一个?你说他们是ByteBuffer 然后你说他们不是。我来到这里是因为问题标题表明这个问题是关于 ByteBuffer,我正在查找文档,但问题似乎根本不是关于 ByteBuffer,尽管标题说是。 【参考方案1】:

查找ReleaseByteArrayElements

【讨论】:

我从本机代码返回 Java 后立即收到此错误。也许是因为释放了内存?我不知道我在这里做什么。 java(3440,0x1135d4000) malloc: *** error for object 0x7fdf6952d7f8: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug 有时它会给出不同的错误。我得到这两个错误中的任何一个。很随意! Invalid memory access of location 0x0 rip=0x1025fd6f7 听起来你在数组边界之外写。 你的发布调用是什么样的?请注意,它释放的是 Java 数组内容的副本,而不是 Java 数组本身。 我认为您在数组中写入的字节数超出了容量。您可以使用 GetArrayLength 找出它有多大。或者以其他方式破坏内存。

以上是关于jbyte* 作为 JNI 中本机 C++ 方法的 ByteBuffer的主要内容,如果未能解决你的问题,请参考以下文章

Java JNI:如何从 C++ 的本机方法设置 Java 类的 String [] 字段

JNI - 在本机 cpp 回调函数中使用 RxJava 的奇怪行为

OSGI 无法在运行时通过 JNI 链接到本机方法

JNI将参数传递给c ++的方法

JNI 通过多个 JNI 调用使 C++ 中的对象保持活动状态

如何加载android系统本机库