英文:
How can i handle a Java internal memory access using JNA
问题
以下是翻译好的内容:
C代码部分:
extern int APIENTRY LSGetDocData(
short hConnect,
HWND hWnd,
unsigned long *NrDoc,
LPSTR FilenameFront,
LPSTR FilenameBack,
LPSTR Reserved1, // not used must be NULL
LPSTR Reserved2, // not used must be NULL
LPHANDLE *FrontImage,
LPHANDLE *BackImage,
LPHANDLE *Reserved3, // not used must be NULL
LPHANDLE *Reserved4, // not used must be NULL
LPSTR CodelineSW,
LPSTR CodelineHW,
LPSTR BarCode,
LPSTR CodelinesOptical,
short *DocToRead,
long *NrPrinted,
LPVOID Reserved5, // not used must be NULL
LPVOID Reserved6);
Java方法部分:
public int LSGetDocData(
short hConnect,
int hWnd,
long[] NrDoc,
String FilenameFront,
String FilenameBack,
String Reserved1,
String Reserved2,
int[] FrontImage,
int[] RearImage,
int[] FrontImage2,
int[] RearImage2,
StringBuffer CodelineSW,
StringBuffer CodelineHW,
StringBuffer Barcode,
StringBuffer CodelinesOptical,
short[] DocToRead,
long[] NrPrinted,
int Reserved5,
int Reserved6);
public int lSGetDocData(long[] nrDoc, int[] frontImage, int[] rearImage, StringBuffer micrHW, StringBuffer barcode, StringBuffer micrSW, StringBuffer codeLineOptical) {
return LsApi.call.LSGetDocData(hConnect[0], hWnd,
nrDoc, "imageF", "ImageR", null, null,
frontImage, rearImage, null, null,
micrSW, micrHW, barcode, codeLineOptical,
new short[0], new long[0], 0, 0);
}
错误部分:
Exception in thread "StartCapture" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy2.LSGetDocData(Unknown Source)
这段代码在使用 IBM Java 1.6 32 位版本时完美运行,但我们想要使用 Oracle Java 1.8 32 位版本,却出现了这个错误。
英文:
the c code is
extern int APIENTRY LSGetDocData(
short hConnect,
HWND hWnd,
unsigned long *NrDoc,
LPSTR FilenameFront,
LPSTR FilenameBack,
LPSTR Reserved1, // not used must be NULL
LPSTR Reserved2, // not used must be NULL
LPHANDLE *FrontImage,
LPHANDLE *BackImage,
LPHANDLE *Reserved3, // not used must be NULL
LPHANDLE *Reserved4, // not used must be NULL
LPSTR CodelineSW,
LPSTR CodelineHW,
LPSTR BarCode,
LPSTR CodelinesOptical,
short *DocToRead,
long *NrPrinted,
LPVOID Reserved5, // not used must be NULL
LPVOID Reserved6);
and my Java method is
public int LSGetDocData(
short hConnect,
int hWnd,
long[] NrDoc,
String FilenameFront,
String FilenameBack,
String Reserved1,
String Reserved2,
int[] FrontImage,
int[] RearImage,
int[] FrontImage2,
int[] RearImage2,
StringBuffer CodelineSW,
StringBuffer CodelineHW,
StringBuffer Barcode,
StringBuffer CodelinesOptical,
short[] DocToRead,
long[] NrPrinted,
int Reserved5,
int Reserved6);
public int lSGetDocData(long[] nrDoc, int[] frontImage, int[] rearImage, StringBuffer micrHW, StringBuffer barcode, StringBuffer micrSW, StringBuffer codeLineOptical) {
return LsApi.call.LSGetDocData(hConnect[0], hWnd,
nrDoc, "imageF", "ImageR", null, null,
frontImage, rearImage, null, null,
micrSW, micrHW, barcode, codeLineOptical,
new short[0], new long[0], 0, 0);
}
the error is
Exception in thread "StartCapture" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy2.LSGetDocData(Unknown Source)
This code works perfectly using IBM Java 1.6 32 bits... but we want to use Oracle Java 1.8 32 bits and we get this error.
答案1
得分: 1
您的类型映射不正确,IBM JDK 可能以与 Oracle 不同的方式处理某些对象(数组、StringBuffer
)的内存指针,使这些不正确的映射似乎能够工作。
一些具体的注意事项:
- 在Java中,
long
是64位的,但在C中,long
可能是32位或64位。您提到您正在使用32位的JRE,但没有提到操作系统的位数。NativeLong
可以处理这种差异。 HWND
在JNA中被映射为扩展HANDLE
,而HANDLE
的大小与指针相同。在32位系统上,int
可以工作,但为了可移植性,应该使用HWND
。- 类似地,
LPHANDLE
被映射为HANDLEByReference
,这是指向指针大小值的指针。 - JNA处理
String
到C字符串的映射,但我不确定关于StringBuffer
。这可能是问题的根源。 - JNA不太好地处理大小为0的数组。我怀疑
new short[0]
或new long[0]
可能会引起问题,因为您定义了一个指向空分配的指针。原生代码是否尝试在这里写入内容?
总之,在32位(或任何位数的Windows)上,long *
映射是错误的,或者在64位上,HWND
和 LPHANDLE
的映射可能是错误的(取决于指针大小)。StringBuffer
的映射可能有问题。0大小的数组不能被写入(所以也许在这里使用 null
是合适的)。
英文:
Your type mappings are not correct, and it is possible that the IBM JDK handled pointers to memory for some objects (arrays, StringBuffer
s) in a different manner than Oracle, permitting these incorrect mappings to appear to work.
Some specific notes:
long
in Java is 64 bits, butlong
can be 32-bits or 64-bits in C. You state you're using a 32-bit JRE but not what the operating system bitness is.NativeLong
can handle this difference.HWND
is mapped in JNA, extendingHANDLE
, which is pointer-sized. On 32-bit systems,int
works, but you should useHWND
for portability.- similarly,
LPHANDLE
is mapped toHANDLEByReference
, a pointer to a pointer-sized value. - JNA Handles the mapping of
String
to C Strings, but I'm not sure aboutStringBuffer
. This could be a source of the problem. - JNA does not handle 0-sized arrays well. I suspect the
new short[0]
ornew long[0]
may be causing problems, as you're defining a pointer to an empty allocation. Does the native code attempt to write something here?
In summary, on 32-bit (or any bitness of Windows) the long *
mapping is wrong, or on 64-bit the HWND
and LPHANDLE
mappings are probably wrong (depending on pointer size). The StringBuffer
mappings might be suspect. And 0-size arrays cannot be written to (so perhaps null
is appropriate there).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论