【发布时间】:2015-09-17 22:26:38
【问题描述】:
您好,我最近在编写 JNA 程序时遇到了问题。
如果我使用 64 位 JVM 运行以下代码,它运行起来很有趣:
public final class UWot {
public static void main(String[] args) {
final int size = 4;
GameProcess process = Processes.get("csgo.exe");
ByteBuffer buff = Buffers.allocate(size).order(ByteOrder.nativeOrder());
Kernel32Direct.ReadProcessMemory(process.handle().getPointer(), 0x178832cc, buff, size, 0);
System.out.println(buff.getInt());
}
}
但如果我使用 32 位 JVM 运行相同的代码,我会收到以下错误:
Exception in thread "main" java.lang.Error: Invalid memory access
at baro.natives.Kernel32Direct.ReadProcessMemory(Native Method)
at temp.hi.main(UWot.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
这是我的读取过程记忆方法:
public final class Kernel32Direct {
public static native int ReadProcessMemory(Pointer process, long address, ByteBuffer memory, int size, int written);
static {
Native.register(NativeLibrary.getInstance("Kernel32", W32APIOptions.UNICODE_OPTIONS));
}
}
编辑结果是 32 位 jvm 正在尝试使用 Kernel32,这是一个 64 位库,因为我使用的是 64 位操作系统并且它们彼此不同意。
所以新问题是,如果它们使用 32 位 JVM 运行,是否可以通过 JNA 直接映射指定使用 32 位内核 32(在 syswow64 中),或者如果它们正在使用,则使用 64 位内核32(在 system32 中) 64位JVM?
【问题讨论】:
-
猜测一下,您访问的本机代码是 64 位的。 32 位 JVM 不能访问 64 位本机代码,64 位 JVM 也不能访问 32 位本机代码。因此,除非您同时拥有 64 位和 32 位版本的本机代码,否则您需要使用与本机代码位匹配的 JVM。
-
我正在读取的进程是 32 位的。由于我的操作系统是 64 位的,难道 Kernel32 是一个 64 位的 dll,这就是问题所在?
-
是的,听起来像。出于某种原因,Microsoft 决定在许多系统 DLL 的名称中保留“32”,即使在 64 位版本的操作系统上也是如此,我一直认为这具有误导性。
-
Kernel32 上是否有任何 32 位副本存储在 64 位窗口上,这样我就可以让我的程序工作,无论他们的 JVM 是什么架构。
-
我不知道(尽管我不是 Windows 专家)。但是,只要用户使用与操作系统位匹配的 JVM(例如 32 位操作系统上的 32 位 JVM),您的代码就应该可以工作。也许您可以捕获异常并优雅地终止,并发出一条消息,通知用户使用正确的 JVM?