NewDirectByteBuffer是否在本机代码中创建副本 我在C++中创建了两个数组,这些数组将在java方面读取: env->NewDirectByteBuffer env->NewByteArray

NewDirectByteBuffer是否在本机代码中创建副本 我在C++中创建了两个数组,这些数组将在java方面读取: env->NewDirectByteBuffer env->NewByteArray,java,c++,java-native-interface,native,Java,C++,Java Native Interface,Native,这些函数是否复制我发送的缓冲区? 是否需要在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"

这些函数是否复制我发送的缓冲区? 是否需要在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完成使用后将其删除

  • :“分配并返回一个直接java.nio.ByteBuffer,它引用从内存地址开始并扩展容量字节的内存块

    “调用此函数并将生成的字节缓冲区对象返回给Java级代码的本机代码应确保缓冲区引用的内存区域有效,可用于读取和(如果合适)写入。从Java代码访问无效内存位置的尝试将返回任意值,没有可见效果,或导致引发未指定的异常。“

    禁止复制

  • :只有参数是
    JNIEnv*
    length
    ,因此没有可复制的内容

  • :“从缓冲区复制回基元数组区域的函数族。”


您使用DirectByteBuffer几乎肯定会以惊人、核心转储和不可预测的方式失败。其行为可能因JVM实现和操作系统而异。问题是您的直接内存必须在DirectByteBuffer的生命周期内保持有效。由于字符串位于堆栈上,因此它将退出堆栈作用域相当快。同时,Java代码可能会或可能不会继续使用DirectByteBuffer,这取决于它是什么。您是否也在编写Java代码?您能否保证在字符串超出作用域之前完成对DirectByteBuffer的使用

即使你能保证这一点,也要意识到Java的GC是不确定的。很容易认为你的DirectByteBuffer不再被使用,但同时它在未声明的对象中游荡,最终被GC覆盖,这可能会调用一些finalize()方法意外地接触到DirectByteBuffer,并且--kablooey!在实践中,除了在应用程序的生命周期中永远不会消失的“共享内存”块之外,很难做出这些保证

NewDirectByteBuffer也没有那么快(至少在Windows中没有),尽管直觉上认为性能就是它的全部。我在实验中发现,复制1000字节比创建单个DirectByteBuffer要快。让Java传递一个字节通常要快得多[]进入C++并将C++复制字节放入其中(AHEM,假设它们适合)。
  • 调用NewByteArray()和SetByteArrayRegion(),返回结果 jBytearray到Java,不用担心
  • 如果性能是 要求,将字节[]从java传递到C++,并用C++填充它 你可能需要两个C++调用,一个获取大小和下一个 获取数据
  • 如果数据很大,请使用NewDirectBtyeBuffer和 确保C++数据“永远”,或者直到你 该死的,我敢肯定那个董事已经被处理掉了

  • <>我也知道C++和java都可以存储相同的文件,这对于大数据非常有用。

    你应该补充说明,开发者应该做<代码> GoistDistBuffelTebug 来获得一个<代码>指针<代码>到缓冲区。@布兰登为什么当他提供缓冲区时,开发者应该调用那个方法?如果我Netro命令缓冲区不复制缓冲区,所以在C++端,我需要确保缓冲区是在堆上分配的,而不是堆栈,以便java端读取一个有效的内存。这是正确的吗?我写的例子是错误的,我应该把字符串的一个拷贝拷贝到一个char *缓冲区。创建一个副本,这样我就可以在堆栈上使用一个字符串,而不用在堆上分配。是这样吗?DirectByteBuffer对于小数据来说实际上速度很慢。只需创建字节[]java java C++无法安全地创建。因为Java不知道数组的大小,Java端不能创建BytErrar并将其发送到C++侧。这就是为什么我需要C++侧创建BuffrHayy的原因,这就是为什么我提到了使用两步方法。第一个从爪哇到C++的调用,要求Java的大小[j]分配字节[]java java C++的第二个调用要求数组填充,因为这个大小是已知的。因为从Java到C++的调用非常快(不像C++调用的Java慢),这对整个时间来说并没有多大的意义。我们在生产中使用了这个技术,它工作得很好。在C++中,我们如何保证传递的字节[]不是一个拷贝?@凯文,当你从java传递到C++时,JyByTurRayPrimes不是一个拷贝,就像你从java到C++的每个对象一样作为方法参数。