Klitos Kyriacou
Klitos Kyriacou

Reputation: 11621

FileChannel.tryLock sometimes throws AccessDeniedException

I've written a small method that is meant to tell me if another instance of the application is already running. I am aware that there are many ways to find out if another instance is running, but I chose this one. I am creating an empty file and keeping it locked for the duration of the application instance. If another instance is running, the tryLock() method is supposed to 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 is a Path for a file in my temp directory.)

When testing this on Windows 7 Professional 64-bit, I found that it works as expected for the first instance and the second attempted instance. However, after the second instance exits (leaving just the first instance running), when a third instance is run, the tryLock() call throws java.nio.file.AccessDeniedException instead of returning null. Can you explain this behaviour? If this is considered normal behaviour, how can I differentiate between an existing instance having the file locked, and a real 'access denied' situation such as an idiot setting the TEMP directory to read-only?

Upvotes: 2

Views: 1483

Answers (1)

Deepak Bhatia
Deepak Bhatia

Reputation: 6276

I made a test project and tested the code the only problem because of which java.nio.file.AccessDeniedException is thrown is StandardOpenOption.DELETE_ON_CLOSE option used in the code.

I removed the option and it works fine now

FileChannel fc = FileChannel.open(MYLOCKFILE, StandardOpenOption.CREATE,
                StandardOpenOption.WRITE);

Explanation that I can think because of which java.nio.file.AccessDeniedException is thrown is that as soon as your second instance terminates the option StandardOpenOption.DELETE_ON_CLOSE [More explaination] will attempt to delete the file on JVM exit and failing might have registered an event in kernel or OS to delete the file as and when possible. So if any other process tries to access, create or write the same file before deletion it throws java.nio.file.AccessDeniedException as a delete operation is already pending for that file.

EDIT

As per your new comment, you can add the following code in try finally block placed after checking alreadyRunning() code.

Snippet Example:

        if(!alreadyRunning())
        {
            try
            {
                // YOUR CODE THAT RUNS  
                while(true)
                {
                    //YOUR 
                    Thread.sleep(35000);                        
                }

            }
            finally
            {

                new File("f:\\test.lock").deleteOnExit();               
            }
        }

Upvotes: 2

Related Questions