FileChannel.tryLock 有时会抛出 AccessDeniedException
FileChannel.tryLock sometimes throws AccessDeniedException
我编写了一个小方法,用于告诉我应用程序的另一个实例是否已经 运行ning。我知道有很多方法可以查明另一个实例是否为 运行ning,但我选择了这个。我正在创建一个空文件并在应用程序实例期间保持锁定状态。如果另一个实例是 运行ning,则 tryLock() 方法应该 return 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 位上进行测试时,我发现它在第一个实例和第二个尝试实例中都按预期工作。但是,在第二个实例退出后(只留下第一个实例 运行ning),当第三个实例为 运行 时,tryLock() 调用抛出 java.nio.file.AccessDeniedException
而不是 return无效。你能解释一下这种行为吗?如果这被认为是正常行为,我如何区分文件已锁定的现有实例和真实的 'access denied' 情况,例如白痴将 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 退出时删除文件并且失败可能已经在内核中注册了一个事件或 OS 以尽可能删除文件。因此,如果任何其他进程在删除之前尝试访问、创建或写入同一文件,它会抛出 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();
}
}
我编写了一个小方法,用于告诉我应用程序的另一个实例是否已经 运行ning。我知道有很多方法可以查明另一个实例是否为 运行ning,但我选择了这个。我正在创建一个空文件并在应用程序实例期间保持锁定状态。如果另一个实例是 运行ning,则 tryLock() 方法应该 return 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 位上进行测试时,我发现它在第一个实例和第二个尝试实例中都按预期工作。但是,在第二个实例退出后(只留下第一个实例 运行ning),当第三个实例为 运行 时,tryLock() 调用抛出 java.nio.file.AccessDeniedException
而不是 return无效。你能解释一下这种行为吗?如果这被认为是正常行为,我如何区分文件已锁定的现有实例和真实的 'access denied' 情况,例如白痴将 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 退出时删除文件并且失败可能已经在内核中注册了一个事件或 OS 以尽可能删除文件。因此,如果任何其他进程在删除之前尝试访问、创建或写入同一文件,它会抛出 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();
}
}