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

如何通过Java JNI向C函数传递空指针(双指针)并读取返回值

解决方案

一、在Java中传递空指针地址给函数

Java本身没有直接的指针类型,我们可以通过ByteBuffer分配原生内存来模拟指针的指针,步骤如下:

  1. 分配一块8字节的原生内存(对应64位系统的指针长度),用来存储初始为空的void*:

    ByteBuffer buffer = ByteBuffer.allocateDirect(8);
    buffer.putLong(0, 0L); // 初始化为NULL指针
    
  2. 通过反射获取这块原生内存的地址(即void**的地址,对应C函数需要的void** pptr参数):

    long ptrPtrAddress = 0;
    try {
        Field addressField = ByteBuffer.class.getDeclaredField("address");
        addressField.setAccessible(true);
        ptrPtrAddress = addressField.getLong(buffer);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
    
  3. 将该地址传给JNI函数:

    int result = AddInSwigJNI.GetClassObject(ptrPtrAddress);
    

二、读取指针指向的数值10

调用函数后,原生内存中存储的void*已经被C函数更新为目标变量的地址,我们可以通过以下步骤读取数值:

  1. 从ByteBuffer中取出更新后的指针地址:

    long targetPtr = buffer.getLong(0);
    
  2. 使用Unsafe类读取该地址指向的int值(注意:Unsafe是内部API,需谨慎使用):

    int value = 0;
    try {
        Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);
        sun.misc.Unsafe unsafe = (sun.misc.Unsafe) unsafeField.get(null);
        value = unsafe.getInt(targetPtr);
        System.out.println("读取到的值:" + value);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
    

重要注意事项

C函数中int value = 10; *pptr = &value;存在严重问题:value是栈上的局部变量,函数返回后该内存会被回收,此时Java中读取该地址会导致野指针访问,程序可能崩溃或出现未知行为。必须修改C代码为堆分配:

intptr_t GetClassObject(void** pptr)
{
    if(!*pptr)
    {
        int* value = (int*)malloc(sizeof(int));
        *value = 10;
        *pptr= value; // 分配堆内存,确保函数返回后有效
        return 0;
    }

    return (intptr_t )*pptr;
}

同时记得在后续逻辑中释放该内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:13:36