tags:

views:

4774

answers:

11

Sometime I see many application such as msn, windows media player etc that are single instance applications (when user executes while application is running a new application instance will not created).

In C#, I use Mutext class for this but I don't know what how to do this in Java?

+14  A: 

If I believe this article, by :

having the first instance attempt to open a listening socket on the localhost interface. If it's able to open the socket, it is assumed that this is the first instance of the application to be launched. If not, the assumption is that an instance of this application is already running. The new instance must notify the existing instance that a launch was attempted, then exit. The existing instance takes over after receiving the notification and fires an event to the listener that handles the action.

Note: Ahe mentions in the comment that using InetAddress.getLocalHost() can be tricky:

  • it does not work as expected in DHCP-environment because address returned depends on whether the computer has network access.
    Solution was to open connection with InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
    Probably related to bug 4435662.
  • I also found bug 4665037 which reports than Expected results of getLocalHost: return IP address of machine, vs. Actual results : return 127.0.0.1.

it is surprising to have getLocalHost return 127.0.0.1 on Linux but not on windows.


Or you may use ManagementFactory object. As explained here:

The getMonitoredVMs(int processPid) method receives as paramter the current application PID, and catch the application name that is called from command line, for example, the application was started from c:\java\app\test.jar path, then the value variable is "c:\java\app\teste.jar". This way, we will catch just application name on the line 17 of the code below. After that, we search JVM for antoher process with the same name, if we found it and the application PID is different, it means that is the second application instance.

JNLP offers also a SingleInstanceListener

VonC
Be aware that the fist solution has a bug. We recently discovered that `InetAddress.getLocalHost()` does not work as expected in DHCP-environment because address returned depends on whether the computer has network access. Solution was to open connection with `InetAddress.getByAddress(new byte[] {127, 0, 0, 1});`.
Ahe
@Ahe: excellent point. I have included your comment as well as Oracle-Sun bug report references in my edited answer.
VonC
+2  A: 

We use file locking for this (grab an exclusive lock on a magic file in the user's app data directory), but we are primarily interested in preventing multiple instances from ever running.

If you are trying to have the second instance pass command line args, etc... to the first instance, then using a socket connection on localhost will be killing two birds with one stone. General algorithm:

  • On launch, try to open listener on port XXXX on localhost
  • if fail, open a writer to that port on localhost and send the command line args, then shutdown
  • otherwise, listen on port XXXXX on localhost. When receive command line args, process them as if the app was launched with that command line.
Kevin Day
A: 

hi there,

You can open a Memory Mapped File and then see if that file is OPEN already. if it is already open, you can return from main.

Other ways is to use lock files(standard unix practice). One more way is to put something into the clipboard when main starts after checking if something is already in the clipboard.

Else, you can open a socket in a listen mode(ServerSocket). First try to connect to hte socket ; if you cannot connect, then open a serversocket. if you connect, then you know that another instance is already running.

So, pretty much any system resource can be used for knowing that an app is running.

BR, ~A

anjanb
A: 

ManagementFactory class supported in J2SE 5.0 or later detail

but now i use J2SE 1.4 and I found this one http://audiprimadhanty.wordpress.com/2008/06/30/ensuring-one-instance-of-application-running-at-one-time/ but I never test. What do you think about it?

Fuangwith S.
I believe it is essentially what is described in the first link of my answer above... http://www.rbgrn.net/blog/2008/05/java-single-application-instance.html
VonC
A: 

You could try using the Preferences API. It is platform independent.

Javamann
I like this idea since the API is simple but maybe some virus scanners wouldn't like you changing the registry so you get similar problems as with using RMI on systems with a software firewall.... not sure.
Cal
+1  A: 

On Windows, you can use launch4j.

Jacek Szymański
A: 

hi,

how can i do it with launchj please tell me.

This is not an answer. Post as a comment on the relevant answer instead. Also remember that this is not a forum.
jackrabbit
+1  A: 

Hi,

I found many techniques to do so. Just see below.It is very helpful.

[http://yuvadeveloper.blogspot.com/2009/02/single-instance-application-in-java.html][1]

+1  A: 

I have found a solution, a bit cartoonish explanation, but still works in most cases. It uses the plain old lock file creating stuff, but in a quite different view:

http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html

I think it will be a help to those with a strict firewall setting.

Ikon
A: 

I used sockets for that and depending if the application is on the client side or server side the behavior is a bit different:

  • client side : if an instance already exists(I cannot listen on a specific port) I will pass the application parameters and exit(you may want to perform some actions in the previous instance) if not I will start the application.
  • server side : if an instance already exists I will print a message and exit, if not I will start the application.
adrian.tarau
A: 

I use the following method in the main method. This is the simplest, most robust, and least intrusive method I have seen so I thought that I'd share it.

private static boolean lockInstance(final String lockFile) {
    try {
        final File file = new File(lockFile);
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
        log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}
Robert