gpt4 book ai didi

java - JNI/外部库调用是否需要直接缓冲区?

转载 作者:行者123 更新时间:2023-11-30 02:56:30 26 4
gpt4 key购买 nike

我想将 Java 对象(尤其是字节数组)的地址传递给系统调用和在一次 JNI 调用中返回的外部函数。

OpenJDK 自己的 JNI 函数的答案显然是 - 例如文件流使用的 readBytes/writeBytes io_util 总是通过 malloc 为与外部调用相关的任何内容引入直接缓冲区/堆。

但是,为什么呢?我检查了 java.nio.Bits (copyFromArray) 和 sun.misc.Unsafe ( copyMemory ) 中的代码,很明显,Java 原始数组的内容可以直接在普通 C 代码中访问,无需任何特殊处理(例如通知 VM 进行内存固定或处理非连续 block )只要它在当前 JNI 函数的范围内即可。所以看起来当调用 JNI 方法时 GC 不会发生,但如果这是真的,为什么 readBytes/writeBytes 总是在 C 堆中复制数据?

谁有这方面的经验吗?我不是在寻求 OpenJDK 或 Oracle 的官方建议/推荐。对可移植性或当前实现之外的任何内容不感兴趣。

最佳答案

使用 GetPrimitiveArrayBytesCritical() 固定数组非常轻量级,正是为此目的而设计的。但 JNI 规范明确描述了 Get/Release 之间可以执行哪些操作...关键:

After calling GetPrimitiveArrayCritical, the native code should not run for an extended period of time before it calls ReleasePrimitiveArrayCritical. We must treat the code inside this pair of functions as running in a "critical region." Inside a critical region, native code must not call other JNI functions, or any system call that may cause the current thread to block and wait for another Java thread. (For example, the current thread must not call read on a stream being written by another Java thread.)

此外,该文档还解释说,JVM 可能在内部以不同的格式表示数组,然后甚至这些函数也会返回一个副本。相反,DirectByteBuffer 保证采用 C 兼容格式。

您的简单实验无法解释的副作用是 Java 或 C 中抛出的异常、来自其他线程的访问,以及显然的替代 JVM。这些规范是在 64 位虚拟内存寻址广泛普及之前制定的,现在没有充分的理由对其进行更改。

所有的 JNI 都被卡住了很多年,因为它一方面“足够好”,另一方面“不够重要”,而且主要关心的是兼容性,这本身就是一个严峻的挑战,因为独立实现的数量。

关于java - JNI/外部库调用是否需要直接缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37110082/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com