java - 使用Java在Windows中读取内存映射文件
问题描述
我使用此示例构建了一个程序,该程序正在创建包含字符串值“来自第一个进程的消息”的内存映射文件。
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[] = TEXT("Local\\MyFileMappingObject");
TCHAR szMsg[] = TEXT("Message from first process.");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR)MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
我的 Java 应用程序读取值时遇到问题。String data = view.getString(0);
上面的演示应用程序运行时给我“java.lang.Error:无效的内存访问”。
我知道函数成功是因为失败(如果应用程序未运行)导致 aNullPointerException
因为this.h
is null
。所以指针是正确的,但是在尝试获取值时我做错了什么?
package ACC;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.W32APIOptions;
public class ACCSharedMemory{
private final MyKernel32 myKernel32;
private HANDLE h;
private Pointer view;
public interface MyKernel32 extends Kernel32 {
MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
}
public ACCSharedMemory() {
myKernel32 = MyKernel32.INSTANCE;
}
public void test() {
h = myKernel32.OpenFileMapping(983071, true, "Local\\MyFileMappingObject");
view = h.getPointer();
String data = view.getString(0);
}
}
编辑。下面的完整工作代码。谢谢丹尼尔和德雷克。
public class ACCSharedMemory{
private final MyKernel32 myKernel32;
private HANDLE h;
private Pointer view;
public interface MyKernel32 extends Kernel32 {
MyKernel32 INSTANCE = (MyKernel32)Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
HANDLE OpenFileMapping(int dwDesiredAccess, boolean bInheritHandle, String lpName);
}
public ACCSharedMemory() {
myKernel32 = MyKernel32.INSTANCE;
}
public void test() {
h = myKernel32.OpenFileMapping(0x4, true, "Local\\MyFileMappingObject");
view = Kernel32.INSTANCE.MapViewOfFile (h, 0x4, 0, 0, 256);
System.out.println(view.getWideString(0));
}
}
解决方案
问题是您将返回HANDLE
的数据视为指向数据的指针。但它不是一个普通的指针;它只对其他文件映射 API 函数有意义。
创建命名共享内存中的示例显示了如何在第二个进程中使用此返回的句柄。请注意,处理检索到的句柄值的本机代码是将其传递给MapViewOfFile()
指定起始偏移量和要映射的字节数,以及共享内存的权限。
该函数将返回指向您可以操作的共享内存的实际指针(例如,检索字符串)。
请注意,Windows 字符串采用 UTF-16 格式,但 usingPointer.getString()
将假定为 8 位 C 字符串。你应该使用Pointer.getWideString()
. 为避免读取超出内存范围,您还应确保Pointer
正在读取的缓冲区足够大以包含空终止符。
推荐阅读
- javascript - 尝试在画布上绘制图像后出现“NS_ERROR_NOT_AVAILABLE”
- javascript - Microsoft 认知服务语音保存选项
- function - 在 MATLAB 中为函数准备输入数
- excel - 如何将工作表的名称与某个输入相匹配?(VBA)
- curl - 如何仅使用 curl 模拟授权代码流
- flutter - 如何在 Flutter 中显示整个芯片文本
- dataframe - 在 DataFrame 中保存 JuMP 优化结果的紧凑方法
- spring-boot - 扩展 ReactiveQueryByExampleExecutor 抛出 PropertyReferenceException
- python - Python 2 和 Python 3 之间过滤器行为的差异
- python - Redis-python 将类型集的多个值添加到 redis 哈希