如何通过Java JNI向C函数传递空指针(双指针)并读取返回值
解决方案
一、在Java中传递空指针地址给函数
Java本身没有直接的指针类型,我们可以通过ByteBuffer分配原生内存来模拟指针的指针,步骤如下:
分配一块8字节的原生内存(对应64位系统的指针长度),用来存储初始为空的
void*:ByteBuffer buffer = ByteBuffer.allocateDirect(8); buffer.putLong(0, 0L); // 初始化为NULL指针通过反射获取这块原生内存的地址(即
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(); }将该地址传给JNI函数:
int result = AddInSwigJNI.GetClassObject(ptrPtrAddress);
二、读取指针指向的数值10
调用函数后,原生内存中存储的void*已经被C函数更新为目标变量的地址,我们可以通过以下步骤读取数值:
从
ByteBuffer中取出更新后的指针地址:long targetPtr = buffer.getLong(0);使用
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
相关产品推荐
相关产品推荐

