Java FileChannel.tryLock有时抛出AccessDeniedException
我编写了一个小方法,用于告诉我应用程序的另一个实例是否已经在运行。我知道有很多方法可以确定另一个实例是否正在运行,但我选择了这个方法。我正在创建一个空文件,并在应用程序实例期间将其锁定。如果另一个实例正在运行,则tryLock()方法应返回null:Java FileChannel.tryLock有时抛出AccessDeniedException,java,nio,filelock,filechannel,Java,Nio,Filelock,Filechannel,我编写了一个小方法,用于告诉我应用程序的另一个实例是否已经在运行。我知道有很多方法可以确定另一个实例是否正在运行,但我选择了这个方法。我正在创建一个空文件,并在应用程序实例期间将其锁定。如果另一个实例正在运行,则tryLock()方法应返回null: private static boolean alreadyRunning() throws IOException { FileChannel fc = FileChannel.open(MYLOCKFILE, S
private static boolean alreadyRunning() throws IOException {
FileChannel fc = FileChannel.open(MYLOCKFILE,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.DELETE_ON_CLOSE);
return fc.tryLock() == null;
}
(MYLOCKFILE是我的临时目录中文件的路径。)
在Windows7 Professional 64位上测试时,我发现它在第一个实例和第二个尝试的实例中都能正常工作。但是,在第二个实例退出后(只让第一个实例运行),当第三个实例运行时,tryLock()调用抛出java.nio.file.AccessDeniedException
,而不是返回null。你能解释一下这种行为吗?如果这被视为正常行为,我如何区分锁定文件的现有实例,一个真正的“拒绝访问”情况,比如一个白痴将临时目录设置为只读?我做了一个测试项目并测试了代码唯一的问题是因为java.nio.file.AccessDeniedException
引发的是StandardOpenOption.DELETE\u ON\u CLOSE
代码中使用的选项
我删除了该选项,现在可以正常工作了
FileChannel fc = FileChannel.open(MYLOCKFILE, StandardOpenOption.CREATE,
StandardOpenOption.WRITE);
我认为,抛出java.nio.file.AccessDeniedException
的原因是,一旦您的第二个实例终止选项StandardOpenOption.DELETE\u ON\u CLOSE
将尝试在JVM退出时删除该文件,如果失败,可能会在内核或操作系统中注册一个事件来删除该文件如果可能的话。因此,如果任何其他进程试图在删除之前访问、创建或写入同一文件,它会抛出java.nio.file.AccessDeniedException
,因为该文件的删除操作已经挂起
编辑
根据您的新注释,您可以在选中alreadyRunning()
code后放置的try finally
块中添加以下代码
代码段示例:
if(!alreadyRunning())
{
try
{
// YOUR CODE THAT RUNS
while(true)
{
//YOUR
Thread.sleep(35000);
}
}
finally
{
new File("f:\\test.lock").deleteOnExit();
}
}
我刚刚意识到我的方法是错误的。抛出的不是tryLock()调用,而是FileChannel.open()调用。第三个实例被另一个进程锁定时无法打开。我无法解释为什么第二个实例成功地打开了通道。在我的固定版本中,当FileChannel.open()抛出时,我使用一个try块来捕获。谢谢。虽然这不是最终的解决方案(我确实希望在JVM退出时删除该文件,因为我喜欢我的应用程序在退出后进行清理),但您的建议为我的解决方案提供了一些线索。@KlitosKyriacou edit to answer将为您的查询提供解决方案