Java巴拿马/外部函数和内存API:读取未知长度的字节数组

问题描述 投票:0回答:1

考虑定义此方法的头文件:

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/76978598https://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 中的字节数组?

java ffi project-panama
1个回答
0
投票

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
函数溢出了您分配的缓冲区的末尾。

© www.soinside.com 2019 - 2024. All rights reserved.