Java Application – Make sure only single/one instance running – with File Lock and ShutdownHook

Often we want to make sure that only 1 instance our application running.
Because something terrible could happen when more than 1 instance running (for example the whole server would exploded and that would make you fired ;) )

Nevertheless what the reason, one of the way to make this happen is by creating a lock file as a sign that an instance is currently running.
So you application will have this flow:

  1. Check if the lock file exists.
  2. Try to delete the lock file to check if there’s really a running process lock the file.
  3. Get the file lock.
  4. If failed to get the lock file, show error that there’s already an instance running
  5. If successfully get the lock then go on with your application want to do.
  6. When application ended/closed release the lock and delete the file lock.

package test.jimmy.filelock;
 
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
 
public class MyApp {
 
private static File f;
private static FileChannel channel;
private static FileLock lock;
 
public static void main(String[] args) {
  try {
    f = new File("RingOnRequest.lock");
    // Check if the lock exist
    if (f.exists()) {
    // if exist try to delete it
    f.delete();
  }
  // Try to get the lock
  channel = new RandomAccessFile(f, "rw").getChannel();
  lock = channel.tryLock();
  if(lock == null)
  {
    // File is lock by other application
    channel.close();
    throw new RuntimeException("Only 1 instance of MyApp can run.");
  }
  // Add shutdown hook to release lock when application shutdown
  ShutdownHook shutdownHook = new ShutdownHook();
  Runtime.getRuntime().addShutdownHook(shutdownHook);
 
  //Your application tasks here..
  System.out.println("Running");
  try {
    Thread.sleep(10000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  } catch(IOException e) {
    throw new RuntimeException("Could not start process.", e);
  }
}
 
public static void unlockFile() {
// release and delete file lock
  try {
    if(lock != null)
    lock.release();
    channel.close();
    f.delete();
  } catch(IOException e) {
    e.printStackTrace();
  }
}
 
static class ShutdownHook extends Thread {
  public void run() {
    unlockFile();
  }
}
 
}

Technorati Tags: , , , , , ,

31 comments

  1. @Zeratul
    Thanks.
    The extra thread is used by ShutdownHook.
    If you see on line 33-34, I add a thread to current Runtime as ShutdownHook.

    Therefore when MyApp ended either normally or killed (windows – end task / linux – kill command), the thread run() method will be called and it’ll release the lock file.

  2. Hi,

    File locking cannot be implemented on Solaris operating system because its file lock is advisory where as on Window platform its mandatory.

    So the provided solution will not lock file on Solaris/linux platform.

    If you know any workaround then please let me know because this bug is not resolved by Java.

    waiting for reply

    Sandeep

  3. Hi,

    >> File locking cannot be implemented on Solaris operating system because its file lock is advisory where as on Window platform its mandatory.

    Any workaround for this?

    Thanks
    Nayn

  4. A FLAW!!
    what if i copy the application to some other directory and run it? in this case, the application can be run easily. rather use a “UNIQUE” location for the “.lock” file or implement the whole mechanism using sockets.
    use some port “xyz” on the system to check the mechanism.

  5. Sorry for not replying your comment fast

    @Nayanish : I’m not really familiar with solaris so I don’t think I can give solution for now.

    @rnb : I assuming you’re creating desktop application with JSE. The concept will be the same, but you need to learn / find tutorial about AWT/Swing.. depends on the one you using.

    @xyz : depends on how you design the locking file folder, the sample was use current folder from where user running it.
    To prevent mistake, you can create example a bash script to running it so it will change to specific folder first.
    Or put the lock file in absolute path.
    Using socket is also a solution, but it will take 1 port for each.. depends on your need, if you need 1000 app with 1000 locking, using port will takes to much port.

  6. Jimmy,

    I just wanted to thank you for this solution. For a schoolproject I need to make a client/server solution, where there can be only one server instance because it has to be bound to a comport. I had tried the port/serversocket solution at first but found out that after longer periods of running ( > 3 days non-stop) the socket appeared to be open again and I could run a a second instance (which fubarred my complete app :D ). Your solution has been stable for 5 days both on a windows and a linux system.

    So again, my thanks :-)

    Cheers!

    Peter
    Groningen, the Netherlands

  7. You can remove the following lines from the code:

    if (f.exists()) {
    // if exist try to delete it
    f.delete();
    }

    So that your code will work in solaris too.

  8. On Red Hat with Java 1.6 I experienced that the f.delete() were allowed and each new process would therefor delete the lock before trying to acquire it. It worked perfectly after I removed the same bit of code as sassubra mentioned.

  9. Hi Jimmy,

    this is the best and cleaner solution I’ve found to the problem! Thanks for posting it!

    The changes sassubra suggested make it works in Linux and Mac OS X too!

  10. Hi Jimmy, good solution, but …
    to use a file for that purpose (global lock) this is also required:
    1. the file must have absolute path given
    2. each application user must have write rights whithin that location

  11. @krzydyn:
    True, we need to be careful on relative path.
    I usually combined it with bash/shell script though to make sure it always executed from same directory.

  12. @jimy I do in similar way. In addition write to this file PID of the process created it. So then I can send a signal (eg. stop it nicely) from external application.
    (at least on unixlike systems)

  13. Hi Jimmy,

    I really like your code and I’d love to implement it in my engineering graduation project. Is it ok if I do so?

    Thank you in advance for your reply and for this great code!

  14. Hi Jim,
    Wonderful article and going through comments , I could find it could work on most OS.
    Till now I was in a belief that kill -9 would not trigger a hook operation, correct if I am wrong.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

WP-SpamFree by Pole Position Marketing