我在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完成后删除它
答案 0 :(得分:3)
你对DirectByteBuffer的使用几乎肯定会以惊人的,核心倾销和不可预测的方式失败。它的行为可能因JVM实现和操作系统而异。问题是您的直接内存必须在DirectByteBuffer的生命周期内保持有效。由于你的字符串在堆栈上,它将很快超出范围。同时,Java代码可能会也可能不会继续使用DirectByteBuffer,具体取决于它是什么。你也在编写Java代码吗?你可以保证在字符串超出范围之前完成对DirectByteBuffer的使用吗?
即使你能保证这一点,也要认识到Java的GC是不确定的。很容易认为你的DirectByteBuffer不再被使用了,但同时它在无人值守的对象中徘徊,最终被GC覆盖,这可能会调用一些意外触及DirectByteBuffer的finalize()方法,和 - kablooey!在实践中,除了“共享内存”块之外,很难做出这些保证,永远不会在应用程序的生命周期内消失。
NewDirectByteBuffer也不是那么快(至少在Windows中没有),尽管直观地假设性能就是它的全部。我通过实验发现,复制1000字节比创建单个DirectByteBuffer要快。让Java将一个byte []传递给C ++并将C ++复制字节放入其中(假设它们适合),通常很多更快。总的来说,我提出了以下建议:
我还读到C ++和Java都可以对同一个文件进行内存映射,这对大数据非常有效。
答案 1 :(得分:1)
NewDirectByteBuffer
:"分配并返回一个直接的java.nio.ByteBuffer,指的是从内存地址开始并扩展容量字节的内存块。
"调用此函数并将生成的字节缓冲区对象返回到Java级代码的本机代码应确保缓冲区引用可供读取的内存的有效区域,并在适当时写入。尝试从Java代码访问无效的内存位置将返回任意值,没有可见效果,或导致抛出未指定的异常。"。
没有复制。
New<Primitive>Array
:只有JNIEnv *
和length
参数,因此无需复制。
Set<Primitive>Array
:&#34;从缓冲区复制原始数组区域的一系列函数。&#34;