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

Touko picture Touko · Aug 27, 2009 · Viewed 8.8k times · Source

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

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

... 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)

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

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

This test was run with Windows 2000.

br, Touko

Answer

djna picture djna · Aug 27, 2009

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

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.

Oddly enough, the discussion about the file locking API when it was under development claimed that Windows OS provided mandatory locking and on Unix only advisory locking. So on that reading one might expect your code to work just fine on 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?

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