FileChannel.tryLock有时会引发AccessDeniedException



我写了一个小方法,用来告诉我应用程序的另一个实例是否已经在运行。我知道有很多方法可以查明另一个实例是否正在运行,但我选择了这个。我正在创建一个空文件,并在应用程序实例期间将其锁定。如果另一个实例正在运行,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。)

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

我做了一个测试项目并测试了代码,因为抛出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();               
            }
        }

相关内容

  • 没有找到相关文章

最新更新