You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过JNI的NewDirectByteBuffer创建的缓冲区能否转为Java可访问的数组?

结论

通过NewDirectByteBuffer创建的是堆外直接缓冲区,本身不依托Java堆内的byte[]实现,无法直接让该ByteBuffer的array()方法返回有效Java数组,这是JDK的固定设计。

可选解决方案

你可以根据场景选择下面两种方案:

  • 允许数据拷贝的场景
    如果你可以接受一次内存拷贝,有两种实现方式:
    1. Java侧自行拷贝:拿到DirectByteBuffer后直接读取内容到新的byte数组即可,代码示例:
    ByteBuffer byteBuf = jniFunctionCall();
    byte[] bytes = new byte[byteBuf.remaining()];
    byteBuf.get(bytes);
    
    1. JNI侧直接返回byte数组:不需要创建DirectByteBuffer,直接创建Java堆数组返回,代码示例:
    jbyteArray jArray = jEnv->NewByteArray(len);
    jEnv->SetByteArrayRegion(jArray, 0, len, (const jbyte*)data);
    // 直接返回该jbyteArray对象到Java侧即可
    
  • 不允许数据拷贝的场景
    如果你要零拷贝操作原生内存,不需要转成byte[],直接调用ByteBuffer自带的get()、put()、读写偏移等API操作数据即可,所有功能和数组访问完全等价,性能没有差异。

注意事项

  • 如果使用JNI直接返回byte数组的方案,原生内存的data指针在调用SetByteArrayRegion完成后即可释放,内容已经拷贝到Java堆托管。
  • 如果继续使用DirectByteBuffer方案,必须保证原生内存data的生命周期长于Java侧持有该ByteBuffer的生命周期,否则会触发非法内存访问崩溃。

内容的提问来源于stack exchange,提问作者Pan Ruochen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 20:45:03