【问题标题】:FileChannel.tryLock sometimes throws AccessDeniedExceptionFileChannel.tryLock 有时会抛出 AccessDeniedException
【发布时间】:2015-12-02 10:02:57
【问题描述】:

我编写了一个小方法,用于告诉我应用程序的另一个实例是否已经在运行。我知道有很多方法可以确定另一个实例是否正在运行,但我选择了这个。我正在创建一个空文件并在应用程序实例期间保持锁定。如果另一个实例正在运行,tryLock() 方法应该返回 null:

private static boolean alreadyRunning() throws IOException {
    FileChannel fc = FileChannel.open(MYLOCKFILE,
            StandardOpenOption.CREATE,
            StandardOpenOption.WRITE,
            StandardOpenOption.DELETE_ON_CLOSE);
    return fc.tryLock() == null;
}

(MYLOCKFILE 是我临时目录中文件的Path。)

在 Windows 7 Professional 64 位上对此进行测试时,我发现它在第一个实例和第二个尝试实例上都按预期工作。但是,在第二个实例退出后(仅让第一个实例运行),当运行第三个实例时,tryLock() 调用将抛出 java.nio.file.AccessDeniedException 而不是返回 null。你能解释一下这种行为吗?如果这被认为是正常行为,我如何区分已锁定文件的现有实例和真正的“访问被拒绝”情况,例如白痴将 TEMP 目录设置为只读?

【问题讨论】:

  • 我刚刚意识到我的方法是错误的。抛出的不是 tryLock() 调用,而是 FileChannel.open() 调用。第三个实例在被另一个进程锁定时无法打开。不知为何二审能成功打开通道。在我的固定版本中,我使用 try 块来捕获 FileChannel.open() 抛出的时间。

标签: java nio filelock filechannel


【解决方案1】:

我做了一个测试项目并测试了代码,唯一导致java.nio.file.AccessDeniedException被抛出的问题是代码中使用的StandardOpenOption.DELETE_ON_CLOSE选项。

我删除了该选项,它现在可以正常工作了

FileChannel fc = FileChannel.open(MYLOCKFILE, StandardOpenOption.CREATE,
                StandardOpenOption.WRITE);

我能想到的解释是 java.nio.file.AccessDeniedException 被抛出是,一旦你的第二个实例终止选项 StandardOpenOption.DELETE_ON_CLOSE [More explaination] 将尝试在 JVM 退出时删除文件并且失败可能已经注册了一个事件内核或操作系统尽可能删除文件。因此,如果任何其他进程在删除之前尝试访问、创建或写入相同的文件,它会抛出 java.nio.file.AccessDeniedException,因为该文件的删除操作已经挂起。

编辑

根据您的新评论,您可以在检查alreadyRunning() 代码后放置的try finally 块中添加以下代码。

片段示例:

        if(!alreadyRunning())
        {
            try
            {
                // YOUR CODE THAT RUNS  
                while(true)
                {
                    //YOUR 
                    Thread.sleep(35000);                        
                }

            }
            finally
            {

                new File("f:\\test.lock").deleteOnExit();               
            }
        }

【讨论】:

  • 谢谢。虽然这不是最终的解决方案(我真的想在 JVM 退出时删除文件,因为我喜欢我的应用程序自行清理),但您的建议为我的解决方案提供了一些线索。
  • @KlitosKyriacou 编辑回答将为您的查询提供解决方案
猜你喜欢
  • 1970-01-01
  • 2017-06-14
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
  • 2015-05-09
  • 2015-04-13
相关资源
最近更新 更多