Java 内存映射Windows中具有共享属性的文件(因此文件不会被锁定以防止删除)
是否有任何方法可以将文件内容映射到Windows中的内存中,而该内存中没有对文件的锁定(特别是,在仍处于mmap状态时可以删除该文件) Java NIO在Windows中库mmap文件的方式是,当堆中还有任何未垃圾收集的MappedByteBuffer引用时,无法删除映射文件。JDK团队声称这是Windows的一个限制,但仅当文件是mmap时,而不是当它们作为常规文件打开时: (显然,如果文件在mmap'd时被删除,那么mmap'd区域到底会发生什么情况在Windows文件语义中是有争议的,尽管它在Linux中定义得很好。) 作为参考,无法在内存映射(或尚未垃圾收集)时删除文件在Java中造成了许多问题: 取消映射操作不受支持还有一些安全原因: 更新:另请参见:如前所述,如果节(文件映射)是在没有属性的情况下以两种方式创建的,则我们可以删除映射文件:Java 内存映射Windows中具有共享属性的文件(因此文件不会被锁定以防止删除),java,windows,mmap,bytebuffer,memory-mapped-files,Java,Windows,Mmap,Bytebuffer,Memory Mapped Files,是否有任何方法可以将文件内容映射到Windows中的内存中,而该内存中没有对文件的锁定(特别是,在仍处于mmap状态时可以删除该文件) Java NIO在Windows中库mmap文件的方式是,当堆中还有任何未垃圾收集的MappedByteBuffer引用时,无法删除映射文件。JDK团队声称这是Windows的一个限制,但仅当文件是mmap时,而不是当它们作为常规文件打开时: (显然,如果文件在mmap'd时被删除,那么mmap'd区域到底会发生什么情况在Windows文件语义中是有争议的,尽
- 打开带有标志的文件-该文件为 在其所有句柄关闭后立即删除,其中 包括指定的句柄和任何其他打开或复制的句柄 把手。或者我们可以使用或 用旗子打电话
- 通过电话。确实
open 带有NtDeleteFile
标志和特殊内部标记的文件 性情这是打电话更多 高效比较正常打开的文件,然后关闭该文件句柄file\u DELETE\u ON\u CLOSE
#ifndef FILE_SHARE_VALID_FLAGS
#define FILE_SHARE_VALID_FLAGS 0x00000007
#endif
NTSTATUS Delete1(PCWSTR FileName)
{
HANDLE hFile = CreateFile(FileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return RtlGetLastNtStatus();
}
CloseHandle(hFile);
return 0;
}
NTSTATUS Delete2(PCWSTR FileName)
{
UNICODE_STRING ObjectName;
if (RtlDosPathNameToNtPathName_U(FileName, &ObjectName, 0, 0))
{
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };
NTSTATUS status = ZwDeleteFile(&oa);
RtlFreeUnicodeString(&ObjectName);
return status;
}
return STATUS_UNSUCCESSFUL;
}
请注意,此处的调用失败,状态为-status\u无法删除
。我建议在这里调用RtlGetLastNtStatus()
,因为win32到错误代码的映射NTSTATUS
不是内射的,并且经常丢失有价值的信息。说STATUS\u CANNOT\u DELETE
映射到ERROR\u ACCESS\u DENIED
。但存在另一个巨大的NTSATUS
代码,该代码也映射到错误\u访问\u拒绝
。错误访问被拒绝
不仅状态访问被拒绝
(实际访问被拒绝)。获取状态\u无法\u删除
此处的信息更多比较错误\u访问被拒绝
。RtlGetLastNtStatus
与从ntdll.dll导出的GetLastError
具有完全相同的签名(因此包括ntdll.lib或ntdllp.lib)
@RbMm,我们可以在关闭打开时删除映射文件(通过
CreateFile
/CloseHandle
或NtDeleteFile
)。在这种情况下,文件系统只检查而不是MmFlushForDelete
。起初这可能是个错误,但现在它已经是标准的了。@eryksun-是的,你纠正了。我们可以通过这种方式删除文件,如果节创建时没有SEC\u IMAGE
attribute@eryksun,是的,如果文件句柄仍未关闭,则从CreateFile
调用中盲目返回RtlGetLastNtStatus()
是可疑的<代码>创建文件可能会在未设置最后一个NT状态值的情况下失败。例如,如果路径太长,翻译将失败,出现状态\u NAME\u too\u long
,在这种情况下,创建文件
只需调用RtlSetLastWin32Error(未找到错误路径)
。状态值未保存在TEBLastStatusValue
中。在第二种情况下,我建议使用rtldospathname tontpathname\U\U with status
,以便我们可能知道调用失败的原因。此函数在NT 5.2+(Server 2003 SP1及更高版本)中可用,因此除非您必须支持旧版本,否则它不是问题。是的,当来自WinAPI时,我们可能需要这两个版本,但我们必须小心,并将其留给调用方。我们可以捕获CreateFile
last status值作为out参数,并返回Windows错误代码。来电者可以决定是否相关。例如,调用方可以忽略ERROR\u PATH\u NOT\u FOUND
的状态。澄清获取错误访问被拒绝的原因非常有用(一个常见且恼人的例子是状态文件\u是\u目录
)。@LukeHutchison-当您可以删除文件时,即使文件正在使用(映射)。文件改为完全删除-从目录中取消映射,不再可见。我们可以说用这样的名称创建新文件。但文件数据最终将被删除后,所有使用它结束。-但这需要win10的最新版本
extern "C" NTSYSCALLAPI NTSTATUS NTAPI RtlGetLastNtStatus();