考虑定义此方法的头文件:
ErrorCode_t GetBlob(Handle_const_t hHandle, uint8_t* const pValue, size_t* const pnSize);
此方法将
n
字节写入从 pValue
指针开始的数组中。尺寸 n
将设置在 pnSize
的指针处。
可以使用 jextract 将标头转换为 Java 源代码,这给出:
public static long GetBlob(MemorySegment hHandle, MemorySegment pValue, MemorySegment pnSize) {
// ..
}
阅读完https://stackoverflow.com/questions/76978598和https://stackoverflow.com/questions/71250218后,我分配了一个具有无界地址布局的
C_POINTER
并调用了该方法:
MemorySegment handle = ..;
MemorySegment arrayPointer = Arena.global().allocate(C_POINTER);
MemorySegment sizePointer = Arena.global().allocate(JAVA_LONG);
Accessor_h.GetBlob(handle, arrayPointer, sizePointer);
通话成功。
sizePointer
包含数组的大小。
但是读取数组数据失败。我尝试了以下方法:
arrayPointer.get(C_POINTER, 0L)
.toArray(JAVA_BYTE); // fails with "Segment is too large to wrap as byte[]. Size: 9223372036854775807"
或者:
arrayPointer.get(C_POINTER, 0L)
.asSlice(0L, sizePointer.get(JAVA_LONG, 0L))
.toArray(JAVA_BYTE); // SIGSEGV (0xb)
或者:
arrayPointer
.toArray(JAVA_BYTE); // seems to contain the correct data, but only the first eight bytes
或者:
arrayPointer
.asSlice(0L, sizePointer.get(JAVA_LONG, 0L))
.toArray(JAVA_BYTE); // fails with "java.lang.IndexOutOfBoundsException: Out of bound access on segment MemorySegment"
如何安全地读取 Java 中的字节数组?
GetBlob
函数看起来正在将字节写入您分配的pValue
缓冲区:
MemorySegment arrayPointer = Arena.global().allocate(C_POINTER);
此缓冲区的大小仅为
8
字节(C_POINTER.byteSize()
的大小)。这可能不是您想要的。相反,您可能想要分配一个字节数组,例如:
long n = ...;
MemorySegment arrayPointer = Arena.global().allocate(uint8_t, n);
其中
n
是缓冲区的大小。
至于读取结果,您最后一次尝试最接近正确。假设您分配的数组大于函数返回的大小。
long bytesWritten = sizePointer.get(JAVA_LONG, 0L);
byte[] arr = arrayPointer
.asSlice(0L, bytesWritten) // will do bounds check
.toArray(JAVA_BYTE);
如果
IndexOutOfBoundsException
抛出 asSlice
,则意味着 GetBlob
函数溢出了您分配的缓冲区的末尾。