如何使用JNA处理Java内部内存访问

huangapple go评论68阅读模式
英文:

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位上,HWNDLPHANDLE 的映射可能是错误的(取决于指针大小)。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, StringBuffers) in a different manner than Oracle, permitting these incorrect mappings to appear to work.

Some specific notes:

  • long in Java is 64 bits, but long 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, extending HANDLE, which is pointer-sized. On 32-bit systems, int works, but you should use HWND for portability.
  • similarly, LPHANDLE is mapped to HANDLEByReference, a pointer to a pointer-sized value.
  • JNA Handles the mapping of String to C Strings, but I'm not sure about StringBuffer. This could be a source of the problem.
  • JNA does not handle 0-sized arrays well. I suspect the new short[0] or new 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).

huangapple
  • 本文由 发表于 2020年8月29日 04:18:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63640391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定