【发布时间】:2022-06-14 13:57:46
【问题描述】:
我正在尝试找出将大量 (20Kb - 2MB) 数据从 C++ 传递到 Android 上的 Java 的最佳方法。我正在使用Djinni 生成尽可能多的桥接代码。我正在考虑的选项是:
-
使用AHardwareBuffer - 看起来像是共享内存的抽象,主要用于 EGL 图像和其他 GLES/Vulkan 渲染需求,但可以在这里使用。因为这里没有与硬件接口,所以我对这里的“硬件”这个词感到不安。也许“硬件”只是意味着该内存可以安全地映射到设备,而我的用例也可以吗?此解决方案需要手动编写一些 JNI 代码。
-
让 Java 提供缓冲区 - 如果 java 通过 C++
bytes[]不会复制数据,只会复制数组的地址。这很笨拙,因为 Java 在分配缓冲区之前必须先询问 C++ 缓冲区应该有多大。该解决方案可以使用自动生成的 JNI 代码。 -
使用NewDirectByteBuffer / java.nio.ByteBuffer.allocateDirect - Sources,没有引用,声称这是一个糟糕的选择,因为它难以管理并且对于少量数据表现不佳。这就是Google recommends。此解决方案需要手动编写一些 JNI 代码。
我倾向于选项 #2,因为它不需要手写任何 JNI 代码并且看起来“足够好”。我还假设这种方法可以反过来很好地工作(即从 Java 到 C++ 的缓冲区没有/低开销共享)。希望在原型设计/基准测试之前得到你们所有人的想法,因为这样做将是一项相当大的投资。
【问题讨论】:
-
为什么不只是一个字节数组?为什么要把事情复杂化?您不需要将数组从 Java 传递给 C,只需让 C 创建数组。担心单个 memcopy 确实是过早的优化。
-
我必须同意@GabeSechan:保持简单并使用
byte数组。public native byte [] getDataFromNativeCode(...);只有 分析你的代码证明将数据复制到Javabyte[]是一个瓶颈,你才让它变得更复杂。你猜怎么着?您的“改进”代码很有可能不会更快。见stackoverflow.com/questions/26603285/… -
我不担心执行 memcpy 所需的 CPU 周期,我担心额外的内存使用。基于这些回应,我稍微放宽了我的方法。但是,我一直在阅读 JNI 规范,并且正在努力寻找可以保证复制(或不复制)的类型。
标签: java android c++ java-native-interface djinni