Java 文件锁定和 Windows - 锁定不是“绝对的”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1339306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:02:52  来源:igfitidea点击:

Java file locking and Windows - the lock isn't "absolute"?

javawindowsfilelock

提问by Touko

I'm trying to lock a file with Java in Windows environment with FileLockand I got an issue : after I lock the file it can still be accessed by other processes at least on some level.

我正在尝试使用FileLock在 Windows 环境中使用 Java 锁定文件,但我遇到了一个问题:在锁定文件后,至少在某种程度上其他进程仍然可以访问它。

Example code follows:

示例代码如下:

public class SimpleLockExample {
    public static void main(String[] args) throws Exception {
        String filename = "loremlipsum.txt";

        File file = new File(filename);
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        FileChannel channel = raf.getChannel();

        FileLock lock = null;
        try {
            lock = channel.tryLock();
            String firstLine = raf.readLine();
            System.out.println("First line of file : " + firstLine);
            waitForEnter();
            lock.release();
        } catch (OverlappingFileLockException e) {
            e.printStackTrace();
        }

        lock.release();
        System.out.println("Lock released");

        channel.close();
    }

    private static void waitForEnter() throws Exception {
        BufferedReader reader =
                new BufferedReader(new InputStreamReader(System.in));
        reader.readLine();
        reader.close();
    }
}

Now, when I lock my file with this example, it is locked :

现在,当我用这个例子锁定我的文件时,它被锁定了:

  • It can't be deleted by Windows
  • Eclipse refuses to open it
  • Windows 无法删除它
  • Eclipse 拒绝打开它

... but it isn't still totally bulletproof:

...但它仍然不是完全防弹的:

  • If I open it with Scite (a text editor), for example, no content is shown but if I select to save the file (empty as opened or with some content written), it succeeds and the contents of the file is cleared... (no content exists there afterwards even if I had written something with Scite)
  • 例如,如果我使用 Scite(文本编辑器)打开它,则不会显示任何内容,但是如果我选择保存文件(打开时为空或写入一些内容),它会成功并清除文件内容。 .(即使我用 Scite 写了一些东西,之后那里也不存在任何内容)

Is there some way to prevent the file totally from being overwritten/cleared by other processes with Java in Windows?

有什么方法可以防止文件完全被 Windows 中使用 Java 的其他进程覆盖/清除?

If I've understood right, I'm using exclusive lock atm. With shared lock there are even more things that can be done.

如果我理解正确,我正在使用独占锁 atm。使用共享锁,可以做更多的事情。

This test was run with Windows 2000.

该测试是在 Windows 2000 上运行的。

br, Touko

br,东子

采纳答案by djna

Tricky, the FileLock API itself doesn't promise much:

棘手的是,FileLock API 本身并没有太大的保证:

This file-locking API is intended to map directly to the native locking facility of the underlying operating system. Thus the locks held on a file should be visible to all programs that have access to the file, regardless of the language in which those programs are written.

Whether or not a lock actually prevents another program from accessing the content of the locked region is system-dependent and therefore unspecified. The native file-locking facilities of some systems are merely advisory, meaning that programs must cooperatively observe a known locking protocol in order to guarantee data integrity. On other systems native file locks are mandatory, meaning that if one program locks a region of a file then other programs are actually prevented from accessing that region in a way that would violate the lock. On yet other systems, whether native file locks are advisory or mandatory is configurable on a per-file basis. To ensure consistent and correct behavior across platforms, it is strongly recommended that the locks provided by this API be used as if they were advisory locks.

此文件锁定 API 旨在直接映射到底层操作系统的本机锁定设施。因此,文件上的锁应该对所有有权访问该文件的程序可见,而不管这些程序是用什么语言编写的。

锁是否真正阻止另一个程序访问锁定区域的内容取决于系统,因此未指定。某些系统的本地文件锁定功能只是建议性的,这意味着程序必须协同遵守已知的锁定协议以保证数据完整性。在其他系统上,本地文件锁是强制性的,这意味着如果一个程序锁定了文件的某个区域,那么实际上会阻止其他程序以违反锁的方式访问该区域。在其他系统上,本机文件锁是建议性的还是强制性的,可以在每个文件的基础上进行配置。为确保跨平台一致和正确的行为,

Oddly enough, the discussion about the file locking API when it was under development claimed that Windows OS provided mandatorylocking and on Unix only advisory locking. So on that reading one might expect your code to work just fine on Windows.

奇怪的是,在开发时关于文件锁定 API 的讨论声称 Windows 操作系统提供强制锁定,而在 Unix 上仅提供建议锁定。因此,在阅读时,人们可能希望您的代码在 Windows 上运行良好。

I wonder if what is happening it that your editor is not so much modifying the file as creating a temporary file and then manipulating directory entries in order to replce the version of the file you have locked with a new version. Would Windows allow such behaviour?

我想知道发生了什么,您的编辑器并没有像创建临时文件那样修改文件,然后操作目录条目以便将您锁定的文件版本替换为新版本。Windows 会允许这种行为吗?

I wonder if you'll need to resort to JNI in order to get the level of control you need.

我想知道您是否需要求助于 JNI 才能获得所需的控制级别。

回答by George

Your call to .tryLock() may return null if it doesn't get the lock. From the Javadoc:

如果没有获得锁,您对 .tryLock() 的调用可能会返回 null。来自 Javadoc:

A lock object representing the newly-acquired lock, or null if the lock could not be acquired because another program holds an overlapping lock

表示新获取的锁的锁对象,如果由于另一个程序持有重叠锁而无法获取锁,则为 null

Also, your code currently opens the file and thenit tries to acquire a lock. Instead you should loop trying to get the lock, and once you've got it, open the file, read the file, close the file, then give up the lock. And give up the lock in a finally {}clause, just in case your code throws an exception with the lock held. (Ever had to reboot a Windows machine just because some file was locked?)

此外,您的代码当前打开文件,然后尝试获取锁。相反,您应该循环尝试获取锁定,一旦获得锁定,打开文件,读取文件,关闭文件,然后放弃锁定。并在finally {}子句中放弃锁,以防万一您的代码在持有锁的情况下抛出异常。(曾经因为某个文件被锁定而不得不重新启动 Windows 机器吗?)