在 Windows 中使用 SHARE 属性对文件进行内存映射(因此文件不会被锁定以防止删除)

2024-02-07

有没有什么方法可以将文件的内容映射到 Windows 中的内存中,而不会锁定文件(特别是,这样可以在仍进行 mmap 时删除文件)?

Java NIO 库在 Windows 中映射文件,这样当堆中留有任何非垃圾收集的 MappedByteBuffer 引用时,就无法删除映射文件。 JDK 团队声称这是 Windows 的限制,但仅当文件被 mmap 时,而不是当它们作为常规文件打开时:

https://mail.openjdk.java.net/pipermail/nio-dev/2019-January/005698.html https://mail.openjdk.java.net/pipermail/nio-dev/2019-January/005698.html

(显然,如果在进行 mmap 处理时删除文件,则 mmap 处理区域究竟会发生什么情况在 Windows 文件语义领域是有争议的,尽管在 Linux 中对此有明确的定义。)

作为参考,在内存映射(或尚未垃圾收集)时无法删除文件会在 Java 中产生很多问题:

http://www.mapdb.org/blog/mmap_files_alloc_and_jvm_crash/ http://www.mapdb.org/blog/mmap_files_alloc_and_jvm_crash/

出于安全原因,不支持取消映射操作:

https://bugs.openjdk.java.net/browse/JDK-4724038 https://bugs.openjdk.java.net/browse/JDK-4724038

更新:另请参阅:如何通过替换为空页映射来取消映射 mmap 文件 https://stackoverflow.com/questions/54337460/how-to-unmap-an-mmapd-file-by-replacing-with-a-mapping-to-empty-pages/55981813#55981813


如前所述@eryksun https://stackoverflow.com/users/205580/eryksun我们可以删除映射文件,如果节(文件映射)是在没有创建的情况下创建的SEC_IMAGE https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createfilemappinga属性有两种方式:

  • 打开文件FILE_FLAG_DELETE_ON_CLOSE https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew flag - 该文件是 在所有句柄关闭后立即删除,这 包括指定的句柄和任何其他打开或重复的句柄 手柄。或者我们可以使用NtOpenFile https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntopenfile or NtCreateFile https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntcreatefile带有标志的呼叫FILE_DELETE_ON_CLOSE https://learn.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntcreatefile.
  • by call ZwDeleteFile https://msdn.microsoft.com/en-us/library/windows/hardware/ff566435(v=vs.85).aspx。真的internal https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/misc.c#L291 NtDeleteFile打开 文件与FILE_DELETE_ON_CLOSE标志和特殊内部 性格DeleteOnly = TRUE https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/misc.c#L339。这是拨打更多电话 高效比较正常打开的文件,然后关闭它句柄。

在代码中看起来像这样。

#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;
}

请注意,调用DeleteFileW https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-deletefilew此处失败,状态为 -STATUS_CANNOT_DELETE。我建议打电话RtlGetLastNtStatus()在这里代替GetLastError() https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx因为win32映射NTSTATUS错误代码不是单射的,经常丢失有价值的信息。说STATUS_CANNOT_DELETE映射到ERROR_ACCESS_DENIED。但存在巨大的另一个NTSATUS代码也映射到ERROR_ACCESS_DENIED. the ERROR_ACCESS_DENIED不仅STATUS_ACCESS_DENIED(真实访问被拒绝)。得到STATUS_CANNOT_DELETE这里提供更多信息比较ERROR_ACCESS_DENIED. the RtlGetLastNtStatus具有完全相同的签名GetLastError并从 ntdll.dll 导出(因此包括ntdll库 or ntdllp库)

extern "C" NTSYSCALLAPI NTSTATUS NTAPI RtlGetLastNtStatus();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Windows 中使用 SHARE 属性对文件进行内存映射(因此文件不会被锁定以防止删除) 的相关文章

  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https

随机推荐