使用Java在Windows中读取内存映射文件

使用Java在Windows中读取内存映射文件,java,winapi,shared-memory,jna,Java,Winapi,Shared Memory,Jna,我使用这个示例构建了一个程序,该程序正在创建包含字符串值“来自第一个进程的消息”的内存映射文件 #包括 #包括 #包括 #包括 #定义BUF_大小256 TCHAR szName[]=TEXT(“Local\\MyFileMappingObject”); TCHAR szMsg[]=文本(“来自第一个进程的消息”); int_tmain() { 处理hMapFile; LPCTSTR-pBuf; hMapFile=CreateFileMapping( 无效的\u句柄\u值,//使用分页文件 NU

我使用这个示例构建了一个程序,该程序正在创建包含字符串值“来自第一个进程的消息”的内存映射文件

#包括
#包括
#包括
#包括
#定义BUF_大小256
TCHAR szName[]=TEXT(“Local\\MyFileMappingObject”);
TCHAR szMsg[]=文本(“来自第一个进程的消息”);
int_tmain()
{
处理hMapFile;
LPCTSTR-pBuf;
hMapFile=CreateFileMapping(
无效的\u句柄\u值,//使用分页文件
NULL,//默认安全性
PAGE_READWRITE,//读/写访问权限
0,//最大对象大小(高阶DWORD)
BUF_SIZE,//最大对象大小(低阶DWORD)
szName);//映射对象的名称
if(hMapFile==NULL)
{
_tprintf(文本(“无法创建文件映射对象(%d)。\n”),
GetLastError());
返回1;
}
pBuf=(LPTSTR)MapViewOfFile(hMapFile,//映射对象的句柄
文件\u映射\u所有\u访问,//读/写权限
0,
0,
大小);
if(pBuf==NULL)
{
_tprintf(文本(“无法映射文件(%d)的视图)。\n”),
GetLastError());
CloseHandle(hMapFile);
返回1;
}
CopyMemory((PVOID)pBuf,szMsg,(_tcslen(szMsg)*sizeof(TCHAR));
_getch();
未经批准的文件(pBuf);
CloseHandle(hMapFile);
返回0;
}
我的Java应用程序在读取值时遇到问题<代码>字符串数据=view.getString(0)在上面的演示应用程序运行时给出“java.lang.Error:无效内存访问”

我知道函数成功是因为失败(如果应用程序未运行)会导致
NullPointerException
,因为
this.h
null
。指针是正确的,但是当我试图获取值时,我做错了什么

package-ACC;
导入com.sun.jna.Native;
导入com.sun.jna.Pointer;
导入com.sun.jna.platform.win32.Kernel32;
导入com.sun.jna.platform.win32.WinNT.HANDLE;
导入com.sun.jna.win32.w32api选项;
公共类ACCSharedMemory{
私有最终MyKernel32 MyKernel32;
私有句柄h;
私有指针视图;
公共接口MyKernel32扩展了Kernel32{
MyKernel32实例=(MyKernel32)Native.load(“kernel32”,MyKernel32.class,W32APIOptions.DEFAULT_OPTIONS);
句柄OpenFileMapping(int-dwDesiredAccess、布尔bInheritHandle、字符串lpName);
}
公共帐户SharedMemory(){
myKernel32=myKernel32.INSTANCE;
}
公开无效测试(){
h=myKernel32.OpenFileMapping(983071,true,“Local\\MyFileMappingObject”);
view=h.getPointer();
字符串数据=view.getString(0);
}
}
编辑。完整的工作代码如下。谢谢丹尼尔和德雷克

公共类ACCSharedMemory{
私有最终MyKernel32 MyKernel32;
私有句柄h;
私有指针视图;
公共接口MyKernel32扩展了Kernel32{
MyKernel32实例=(MyKernel32)Native.load(“kernel32”,MyKernel32.class,W32APIOptions.DEFAULT_OPTIONS);
句柄OpenFileMapping(int-dwDesiredAccess、布尔bInheritHandle、字符串lpName);
}
公共帐户SharedMemory(){
myKernel32=myKernel32.INSTANCE;
}
公开无效测试(){
h=myKernel32.OpenFileMapping(0x4,true,“Local\\MyFileMappingObject”);
view=Kernel32.INSTANCE.MapViewOfFile(h,0x4,0,0,256);
System.out.println(view.getWideString(0));
}
}

问题在于,您将返回的
句柄
视为指向数据的指针。但它不是一个简单的指针;它只对其他文件映射API函数有意义

处的示例演示如何在第二个进程中使用此返回句柄。注意,处理检索到的句柄值的本机代码是将其传递给指定起始偏移量和要映射的字节数,以及共享内存的权限

该函数将返回指向共享内存的实际指针,然后可以对其进行操作(例如,检索字符串)


请注意,Windows字符串采用UTF-16格式,但使用
指针。getString()
将假定为8位C字符串。您应该使用
指针.getWideString()
。为避免读取超出内存边界,还应确保正在读取的
指针处的缓冲区足够大,足以包含空终止符。

是否有可能使用小的工作代码?已尝试getWideString()。同样的问题。还尝试了:view=Kernel32.INSTANCE.MapViewOfFile(h,MyKernel32.FILE\u READ\u ONLY,0,0,256);但该行之后的视图为空。@TomaszMakowski文件映射的只读访问权限应为
file\u map\u read(0x4)
而不是
file\u read\u only(0x8)
。在
MapViewOfFile
之后,您是否收到任何错误代码?
MapViewOfFile
将0x8标识为
SECTION\u MAP\u EXECUTE
。您没有在
CreateFileMapping
中指定
PAGE\u EXECUTE.*
访问权限。另一个简要说明。。。您应该在
h
上调用
CloseHandle()
以释放句柄,在
view
上调用
UnmapViewOfFile()
以释放该本机内存.Thx。还有一个问题。当我在MyFileMappingObject中有一个结构时,我会这样做:t.smVersion=view.getWideString(0);t.acVersion=view.getWideString(30);t.numberOfSessions=view.getInt(60);等等您认为在Java中有一种更简单的方法从对象上的内存映射结构吗?如果使用JNA
结构,您可以使用指针构造函数来实现这一点。不过,这会将结构映射绑定到共享内存,因此可能不是最好的解决方案,因为它显示了将字节映射到对象的另一种可能性。您仍然需要将字符串映射到
byte[]
并对其使用
Native.toWideString()