Java 当sizeof(long)为4时,为什么我需要为JNA指针保留超过4个字节来接收long?
我正在使用JNA与使用Visual Studio 2015编译的本机C库进行通信。我在一台64位机器上工作。我试图通过长指针Java 当sizeof(long)为4时,为什么我需要为JNA指针保留超过4个字节来接收long?,java,jna,Java,Jna,我正在使用JNA与使用Visual Studio 2015编译的本机C库进行通信。我在一台64位机器上工作。我试图通过长指针long*pdays参数接收C函数的值。我得到以下异常: java.lang.IndexOutOfBoundsException:边界超出可用空间: com.sun.jna.Memory.boundsCheck(Memory.java:220)上的size=4,offset=8 位于com.sun.jna.Memory.getLong(Memory.java:498) 我不
long*pdays
参数接收C函数的值。我得到以下异常:
java.lang.IndexOutOfBoundsException:边界超出可用空间:
com.sun.jna.Memory.boundsCheck(Memory.java:220)上的size=4,offset=8
位于com.sun.jna.Memory.getLong(Memory.java:498)
我不明白我在这里遗漏了什么,如果我只为指针保留4字节的内存,这会导致上面的崩溃,但是如果我保留8字节,一切都会正常。但是sizeof(long)返回4,那么为什么我需要保留超过4个字节呢
System.out.println(NativeLong.SIZE); // --> 4
System.out.println(Native.LONG_SIZE); // --> 4
// Pointer pDays = new Memory(Native.LONG_SIZE); Results in IndexOutOfBoundsException
Pointer pDays = new Memory(8); //
nativeLib.GetDaysUntilExpiration(pDays);
return pDays.getLong(0); // crashes here when reserving just 4 bytes
它崩溃是因为您试图从仅分配了4个字节的本机内存中读取8个字节 无论本机类型是什么,也不管它只有4个字节。
内存
只包含4个字节,您可以用任何方式解释它们。你可以得到一个byte[]
数组,或者一个int
(包含这4个字节),或者甚至一个short
或者byte
只读取这个字节数。您甚至可以尝试使用字符串
(虽然没有空终止符,但您可能会读取远远超过允许的4个字节,谁知道会得到什么,因此这将是危险的。)
您要求获取一个Javalong
,它是一个8字节的变量;相应地,代码检查偏移量中的下8个字节是否适合分配的内存。Memory.java
中的代码具有以下硬编码:
boundsCheck(offset, 8);
javadoc很清楚这是为什么:
间接指向malloc
空间的本机指针,一个la指针.getLong
。
但此方法执行边界检查以确保
间接寻址不会导致malloc
ed空间之外的内存被删除
访问
在不手动分配空间的情况下,正确的做法是使用NativeLongByReference
。JNA将自行负责空间的分配和值的检索,您不必担心本机大小
NativeLongByReference pDays = new NativeLongByReference();
nativeLib.GetDaysUntilExpiration(pDays);
return pDays.getValue().longValue();
编辑:我注意到您在评论中说“C函数参数是指针,使用NativeLongByReference将导致”LongByReference无法转换为指针--这不是C函数的问题,而是接口中的JNA映射的问题。最好将
getdaysuntileexpiration
的JNA映射更改为采用NativeLongByReference
参数。如果无法更改该函数的JNA映射,可以使用pDays.getPointer()
作为参数来解决此问题 在java中,long总是8个字节。也许你想让getInt读取4字节这只是一个没有保证的想法,这是很久以前的事了,我的C技能有点生疏了,但是在x64位的机器/操作系统上(我不知道你是否使用了),C指针应该是8字节大。。。可能这就是问题的原因我不会直接使用指针和内存,但我会使用NativeLongByReference:C函数参数是指针,使用NativeLongByReference将导致“LongByReference无法转换为指针”,即不兼容的类型错误。