Jimmy's Blog

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

by jimmy on Jul.21, 2008, under English, Java, Programming

[Switch to Mobile Edition]

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: , , , , , ,

Related posts:

  1. Jimmy’s Blog – Send & Receiving SMS on specific Port with J2ME Application
  2. Simple Log4J implementation
  3. Java 6 "Mustang"
  4. Java – Adding new Classpath at Runtime
  5. Java ME (J2ME) JSON Implementation For Array Object

:, , , , , ,

30 Comments for this entry

  • Zeratul

    hi, nice article, why that extra thread for unlocking?

  • jimlife

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

  • santiago

    Thank you very much, the post is very precise and very good results.

  • jimlife

    @santiago
    You’re welcome.
    Good to know that my blog can help you.

  • Zeratul

    Yes now I understand :) , just ctrl+c-ed javaApp that echoed using shutdown hook. Thanks

  • Guilherme Costa

    Jim,

    AWESOME solution, it works great!!

    Thanks a lot,
    Gui

  • Sandeep Chauhan

    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

  • Thomas

    Works great. Thank you!

  • Nayanish

    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

  • rnb

    “show error that there’s already an instance running” – how show that “error” in the dialog window?

  • xyz

    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.

  • jimmy

    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.

  • Peter Davids

    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

  • jimmy

    @Peter:
    Glad my article can help you
    Cheers :)

  • sassubra

    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.

  • Derek

    @Sassubra
    Why would that work?

  • Omar

    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.

  • Yi

    Hey this approach does not work on Linux.

  • Yi

    do you have solution for Linux mate?

  • jimmy

    @Yi: I think it should work on Linux.
    Do the file created when the app run?

  • Lee

    What about just binding a port? This is enforced as a non shared kernel resource, and cleaned up on process exit by the OS…..

  • jimmy

    Binding a port is also another possible solution, the disadvantages is you gonna used 1 port available on your OS.

  • Federico

    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!

  • krzydyn

    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

  • jimmy

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

  • krzydyn

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

  • Jaton

    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!

  • jimmy

    @Jaton: you’re welcome. Feel free to use/copy my blog code. Glad it can help

  • Venkat

    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.

  • donne sole annunci

    Hi my family member! I wish to say that this article is amazing, nice written and include approximately all vital infos. I’d like to see extra posts like this .

Leave a Reply

Spam Protection by WP-SpamFree

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...