我正在c++中创建两个数组,这些数组将在Java端读取:

env->NewDirectByteBuffer
env->NewByteArray

这些功能会复制我发送的缓冲区吗?
我是否需要在c++端的堆上创建缓冲区,还是可以在堆栈上创建缓冲区,因为jvm会复制它?

例如,此代码可以正常运行:
std::string stam = "12345";
const char *buff = stam.c_str();
jobject directBuff = env->NewDirectByteBuffer((void*)buff, (jlong) stam.length() );

另一个例子:
std::string md5 "12345";
jbyteArray md5ByteArray = env->NewByteArray((jsize) (md5.length()));
env->SetByteArrayRegion(md5ByteArray, 0, (jsize) (md5.length()), (jbyte*)
 md5.c_str());

在堆栈上创建字符串。此代码将始终有效,还是我需要在堆上创建这些字符串,并负责在Java使用完之后删除它?

最佳答案

您对DirectByteBuffer的使用几乎肯定会以惊人的,核心转储和不可预测的方式失败。而且其行为在JVM实现和操作系统之间可能有所不同。问题在于您的直接内存必须在DirectByteBuffer的生存期内保持有效。由于您的字符串在堆栈中,因此它将很快超出范围。同时,Java代码可能会或可能不会继续使用DirectByteBuffer,具体取决于它是什么。您也在编写Java代码吗?您可以保证在字符串超出范围之前对DirectByteBuffer的使用已经完成吗?

即使可以保证,也要意识到Java的GC是不确定的。很容易以为不再使用您的DirectByteBuffer,但是与此同时,它却徘徊在未回收的对象中,这些对象最终被GC悬停了,它可能会调用某些finalize()方法,而该方法意外地碰到了DirectByteBuffer ,还有-kablooey!在实践中,很难做到这些保证,除非“共享内存”块在应用程序的生命周期内永不消失。

NewDirectByteBuffer也没有那么快(至少在Windows中不是这样),尽管直观地认为性能才是真正的关键。我从实验上发现,复制1000个字节比创建单个DirectByteBuffer更快。通常,让Java将byte []传递给C++并让C++复制字节(通常,假设合适)可以更快。总体而言,我提出以下建议:

  • 调用NewByteArray()和SetByteArrayRegion(),返回结果
    jBytearray到Java,没有后顾之忧。
  • 如果性能是
    要求,将byte []从Java传递到C++并用C++填充
    in。您可能需要两个C++调用,一个调用获取大小,第二个调用
    获取数据。
  • 如果数据量很大,请使用NewDirectBtyeBuffer和
    确保C++数据保持“永远”不变,或者直到您
    无法确定DirectByteBuffer已被处置。

  • 我还读过C++和Java都可以对同一文件进行内存映射,这对于大型数据非常有用。

    关于java - NewDirectByteBuffer用 native 代码创建拷贝吗,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28791827/

    10-11 20:49