简体   繁体   English

java.lang.Error:32 位 Windows 上的内存访问无效

[英]java.lang.Error: Invalid memory access on 32 bit Windows

I have JNA wrapper for a C DLL.我有一个 C DLL 的 JNA 包装器。 It works fine, except when used on a Windows 32-bit system.它工作正常,除非在 Windows 32 位系统上使用。 Here is a simplified example:这是一个简化的示例:

int SetData(const wchar_t* data);

int SetId(const wchar_t* id, uint32_t flags);

I created JNA bindings as follows:我创建了 JNA 绑定如下:

public static native int SetData(WString data);

public static native int SetId(WString id, int flags);

The first function SetData() works fine on both 32-bit as well as 64-bit Windows, but the second function crashes on Windows 7 32-bit.第一个函数 SetData() 在 32 位和 64 位 Windows 上都可以正常工作,但第二个函数在 Windows 7 32 位上崩溃。

I tried using NativeLong as suggested in other related posts, but it didn't help.我尝试按照其他相关帖子中的建议使用 NativeLong,但没有帮助。

Here is the link to the repository:这是存储库的链接:

https://github.com/cryptlex/lexactivator-java/blob/master/src/main/java/com/cryptlex/lexactivator/LexActivatorNative.java https://github.com/cryptlex/lexactivator-java/blob/master/src/main/java/com/cryptlex/lexactivator/LexActivatorNative.java

There is very likely a bug in the Windows 32-bit DLL. Windows 32 位 DLL 中很可能存在错误。

Your mappings are correct: WString is the correct mapping for const wchar_t* , and int (always 32 bits in Java) is the correct mapping for uint32_t (always 32 bits), with a caveat about signededness that shouldn't matter when used as a flags bitmask.您的映射是正确的: WStringconst wchar_t*的正确映射,而int (在 Java 中始终为 32 位)是uint32_t (始终为 32 位)的正确映射,但有一个关于有符号性的警告,当用作标志位掩码。

I'm not sure where you read that NativeLong would be appropriate here.我不确定你在哪里读到NativeLong在这里合适。 This is primarily intended for *nix native code in which sizeof(long) differs based on the OS bitness.这主要用于 *nix 本机代码,其中sizeof(long)因操作系统位数而异。 Practically, it doesn't actually matter on Windows since LONG is always 32-bit, but it involves unnecessary object creation vs. a primitive.实际上,它在 Windows 上实际上并不重要,因为LONG总是 32 位,但它涉及不必要的对象创建与原始对象。

The "Invalid Memory Access" error thrown by JNA is a "graceful" handling of native memory errors caught by Structured Exception Handling . JNA 抛出的“无效内存访问”错误是对Structured Exception Handling捕获的本机内存错误的“优雅” 处理 All you really need to know is that You are attempting to access native memory that you do not own.您真正需要知道的是,您正在尝试访问不属于您的本机内存。

Debugging these errors always involves carefully tracking memory allocations.调试这些错误总是涉及仔细跟踪内存分配。 When is memory allocated?什么时候分配内存? When is it released?什么时候发布? Who (Java-side or native side) is responsible for this allocation?谁(Java 端或本机端)负责此分配? Your program is likely crashing at the point you attempt to copy data from the user-provided ID string to some native memory that your native DLL is accessing.当您尝试将数据从用户提供的 ID 字符串复制到您的本机 DLL 正在访问的本机内存时,您的程序可能会崩溃。 So that points to two memory pointers you need to investigate.所以这指向你需要调查的两个内存指针。

  • Look at the memory where the ID string is being written.查看正在写入 ID 字符串的内存。 Find out when the memory for it is allocated.找出为它分配内存的时间。 Ensure it is large enough for the string (should be 2x string length + 2 bytes for a null terminator) and properly zeroed (or a null byte explicitly appended).确保它对于字符串来说足够大(对于空终止符应该是 2x 字符串长度 + 2 个字节)并正确归零(或明确附加一个空字节)。 Verify all WinAPI calls use the correct (W vs. A) unicode version.验证所有 WinAPI 调用都使用正确的(W 与 A)unicode 版本。

    • I tried adding LA_IN_MEMORY to the flags bitmask and got an error message "Either trial has not started or has been tampered! Trial days left: 30".我尝试将LA_IN_MEMORY添加到flags位掩码并收到错误消息“试用尚未开始或已被篡改!试用天数:30”。 This is apparently produced by the next line ( IsLicenseGenuine() ), meaning that the setProductId() call was successful.这显然是由下一行 ( IsLicenseGenuine() ) 产生的,这意味着setProductId()调用成功。
    • Identifying what your native code does differently when the LA_IN_MEMORY flag is not set will probably be very helpful.在未设置LA_IN_MEMORY标志时识别您的本机代码的不同之LA_IN_MEMORY可能会非常有帮助。 It's possible the invalid memory access is associated with identifying the directory or file to be used.无效的内存访问可能与识别要使用的目录或文件有关。
      • There is a recent changelog entry for 3.14.9 involving this flag. 3.14.9 最近有一个涉及这个标志的变更日志条目。 Looking at that commit might give a hint to the problem.查看该提交可能会提示问题。
      • There's another recent change in 3.15.0 involving auto-detection of a file on Windows which also may be suspicious given that LA_IN_MEMORY makes the problem go away. 3.15.0 中还有另一个最近的变化,涉及自动检测 Windows 上的文件,鉴于LA_IN_MEMORY使问题消失,这也可能是可疑的。
    • When given an invalid key, the error message "43: The product id is incorrect."当给出无效密钥时,错误消息“43:产品 ID 不正确”。 is returned, so the point in native code where unowned memory is being accessed is after this error check.返回,因此本机代码中访问无主内存的点是在此错误检查之后。
  • Trace what is happening with the ID string defined on the Java side.跟踪 Java 端定义的 ID 字符串发生的情况。 Given the constant definition of the string, the actual memory allocation is likely not a problem, but keep track of the native pointer to this string to be sure it's not inadvertently overwritten.鉴于字符串的常量定义,实际的内存分配可能不是问题,但请跟踪指向该字符串的本机指针以确保它不会被无意中覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM