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

Java Foreign API从C_POINTER获取UDID报错,如何解决?

解决Java Foreign API调用libimobiledevice获取UDID的IndexOutOfBoundsException问题

错误原因

你的错误源于对C指针在Java Foreign API中的处理逻辑理解偏差:

  • 在目标C代码中,idevice_get_udid(device, &udid)是将UDID字符串的指针赋值给udid(传入的是char**类型的指针)。
  • 你的Kotlin代码中,udidAddress是分配的C_POINTER类型内存段(对应C的char**),但你直接用udidAddress.address()获取的是这个指针变量自身的内存地址,而非它指向的UDID字符串的地址,导致后续读取字符串时访问了无效内存区域,触发IndexOutOfBoundsException。
  • 此外,原代码中idevice_free(deviceAddress)的调用也有误,应该传入deviceAddress内部存储的设备指针,而非deviceAddress本身。

修正方案

需要从udidAddress中读取它存储的实际指针值(对应C中*udid的地址),再用这个地址创建MemorySegment读取UDID字符串;同时修正idevice_free的调用参数。

修正后的Kotlin代码

class Device {
    private val arena: Arena = Arena.openConfined()
    private val udidAddress: MemorySegment = arena.allocate(C_POINTER)
    private val deviceAddress: MemorySegment = arena.allocate(C_POINTER)

    init {
        if (idevice_new_with_options(deviceAddress, NULL(), IDEVICE_LOOKUP_USBMUX()) != IDEVICE_E_SUCCESS()) {
            throw Exception("ERROR: No device found!")
        }
        if (idevice_get_udid(deviceAddress, udidAddress) != IDEVICE_E_SUCCESS()) {
            // 读取deviceAddress中存储的设备指针,再传递给idevice_free
            val devicePtr = deviceAddress.get(C_POINTER, 0)
            idevice_free(devicePtr)
            throw Exception("ERROR: Get UDID failed")
        } else {
            println("connected")
            // 从udidAddress中读取指向UDID字符串的指针
            val udidPtr = udidAddress.get(C_POINTER, 0)
            // 用该指针创建MemorySegment并读取UTF-8字符串
            println(udidPtr.getUtf8String(0))
        }
    }
}

fun main() {
    Device()
}

补充说明

  • 如果没有显式定义C_POINTER,可以用ValueLayout.ADDRESS替代,两者均对应C语言中的指针类型。
  • 根据libimobiledevice官方文档,idevice_get_udid返回的UDID字符串由库内部管理,无需手动释放;但设备指针必须在使用完毕后调用idevice_free释放,修正后的代码已处理此逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:17:49