Java one instance running

How to allow running only one instance of a Java program at a time?

I think your suggestion of opening a port to listen when you start your application is the best idea.

It’s very easy to do and you don’t need to worry about cleaning it up when you close your application. For example, if you write to a file but someone then kills the processes using Task Manager the file won’t get deleted.

Also, if I remember correctly there is no easy way of getting the PID of a Java process from inside the JVM so don’t try and formulate a solution using PIDs.

Something like this should do the trick:

private static final int PORT = 9999; private static ServerSocket socket; private static void checkIfRunning() < try < //Bind to localhost adapter with a zero connection queue socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] )); > catch (BindException e) < System.err.println("Already running."); System.exit(1); >catch (IOException e) < System.err.println("Unexpected error."); e.printStackTrace(); System.exit(2); >> 

This sample code explicitly binds to 127.0.0.1 which should avoid any firewall warnings, as any traffic on this address must be from the local system.

Читайте также:  Php mysqli set names

When picking a port try to avoid one mentioned in the list of Well Known Ports. You should ideally make the port used configurable in a file or via a command line switch in case of conflicts.

Solution 2

As the question states that WebStart is being used, the obvious solution is to use javax.jnlp.SingleInstanceService .

This service is available in 1.5. Note that 1.5 is currently most of the way through its End Of Service Life period. Get with Java SE 6!

Solution 3

I think that the better idea would be to use file lock (quite an old idea 🙂 ). Since Java 1.4 a new I/O library was introduced, that allows file locking.

Once the application starts it tries to acquire lock on a file (or create it if does not exist), when the application exits the lock is relased. If application cannot acquire a lock, it quits.

The example how to do file locking is for example in Java Developers Almanac.

If you want to use file locking in Java Web Start application or an applet you need to sing the application or the applet.

Solution 4

You can use JUnique library. It provides support for running single-instance java application and is open-source.

Solution 5

We do the same in C++ by creating a kernal mutex object and looking for it at start up. The advantages are the same as using a socket, ie when the process dies/crashes/exits/is killed, the mutex object is cleaned up by the kernel.

I’m not a Java programmer, so I am not sure whether you can do the same kind of thing in Java?

Источник

How to Implement a Single Instance Java Application

How to implement a single instance Java application?

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[] ) ;

  • 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 parameter 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\\test.jar «. This way, we will catch just application name on the line 17 of the code below.

After that, we search JVM for another 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

Run one instance of java application

A simple way to have one instance is to use a service port.

ServerSocket ss = new ServerSocket(MY_PORT);

The benefit of using this approach instead of a locking a file is that you communicate to the instance already running and even check it is working. e.g. if you can’t start the server socket use a plain Socket to send it a message like «open a file for me»

Java Application with Single Instance per User

Sockets will be a bit problematic if you want the application to run concurrently under different users.

The option of using an NIO FileLock is possible. You create the file under the user’s directory so that another user can have his own lock file. The key thing to do here is to still try to acquire the file lock if the file exists already, by attempting to delete it before recreating it. This way if the application crashes and the file is still there, you will still be able to acquire a lock on it. Remember that the OS should release all locks, open file handles and system resources when a process terminates.

 public ExclusiveApplicationLock 
throws Exception
private final File file;
private final FileChannel channel;
private final FileLock lock;

private ExclusiveApplicationLock()
String homeDir = System.getProperty("user.home");

file = new File(homeDir + "/.myapp", app.lock");
if (file.exists()) file.delete();
>

channel = new RandomAccessFile(file, "rw").getChannel();
lock = channel.tryLock();
if (lock == null) channel.close();
throw new RuntimeException("Application already running.");
>

Runtime.getRuntime().addShutdownHook(new Thread(() -> releaseLock());
>

private void releaseLock() try if (lock != null) lock.release();
channel.close();
file.delete();
>
>
catch (Exception ex) throw new RuntimeException("Unable to release application process lock", ex);
>
>
>

Another alternative is to use a library that does this for you like Junique. I haven’t tried it myself but you could have a go. It seems very old but I guess there isn’t much that needs to change in something like this, nothing much changed in NIO since Java 1.4.

It is on Maven Central though so you can import it easily.
https://mvnrepository.com/artifact/it.sauronsoftware/junique/1.0.4

If you look at the code you will see that it does the same thing with file locks:
https://github.com/poolborges/it.sauronsoftware.junique/blob/master/src/main/java/it/sauronsoftware/junique/JUnique.java

How to make sure that only a single instance of a Java application is running?

What you are looking for can probably best be accomplished with a lock file. By lock file I simply mean a file that will have a predefined location and whose existence is your mutex.

Test if that file exists when your program starts, if it does, exit immediately. Create a file in a known location. If your program exits normally, delete the lock file.

Probably best is if you can also populate the file with a pid (process id) so that you can detect abnormal exits that didn’t delete the file but this get OS specific.

How to allow running only one instance of a Java program at a time?

I think your suggestion of opening a port to listen when you start your application is the best idea.

It’s very easy to do and you don’t need to worry about cleaning it up when you close your application. For example, if you write to a file but someone then kills the processes using Task Manager the file won’t get deleted.

Also, if I remember correctly there is no easy way of getting the PID of a Java process from inside the JVM so don’t try and formulate a solution using PIDs.

Something like this should do the trick:

private static final int PORT = 9999;
private static ServerSocket socket;

private static void checkIfRunning() try //Bind to localhost adapter with a zero connection queue
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] ));
>
catch (BindException e) System.err.println("Already running.");
System.exit(1);
>
catch (IOException e) System.err.println("Unexpected error.");
e.printStackTrace();
System.exit(2);
>
>

This sample code explicitly binds to 127.0.0.1 which should avoid any firewall warnings, as any traffic on this address must be from the local system.

When picking a port try to avoid one mentioned in the list of Well Known Ports. You should ideally make the port used configurable in a file or via a command line switch in case of conflicts.

How to let run only one instance of application at a time?

You could try JUnique. It’s an open source library doing exactly what you ask for. Import junique-1.0.4.jar to your project as a library. It’s just 10kb file.

It’s manual neatly describes how to implement it on a project. For a JavaFX application, implementation would look something like this:

Make sure to import these classes to your main

import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
 public static void main(String[] args)  
String appId = "myapplicationid";
boolean alreadyRunning;
try JUnique.acquireLock(appId);
alreadyRunning = false;
> catch (AlreadyLockedException e) alreadyRunning = true;
>
if (!alreadyRunning) launch(args); // >else < //This else is optional. Just to free up memory if you're calling the program from a terminal.
System.exit(1);
>
>

check for single instance java program

Launch the application using Java Web Start and implement the SingleInstanceService of the JNLP API. Here is a demo. of the SingleInstanceService .

If it attempted to open another instance of the program I would like the current instance to be brought to the foreground.

Hook that up in the newActivation(String[]) method of the SingleInstanceListener . It will be passed any arguments that were provided for the new launch. The existing instance gets to decide what to do with the new args (e.g. change file, add new tab, ignore..)

Источник

Single Running Instance of a Java Application

This article was last edited over 3 years ago. Information here may no longer be accurate. Please proceed with caution, and feel free to contact me.

I’ve been trying to find a reliable way to make sure I only have a single instance of a running Java application. A lot of suggestions I found online recommended opening a Socket on a specific port that you reserve for your program. I don’t like this approach because it seems a bit short-sighted. If another program needs to be deployed on your computer(s) and that program uses the same port as your own then you have a conflict. Imagine your program is deployed to a few thousand computers. Now you have a major issue.

Another popular answer is to write a sort of Lock File. If this file exists or has a certain value, you assume the application is running. When the program is shutdown cleanly you delete this lock file. My issue with this approach is that a sudden power loss to your system might result in your application not closing or unlocking the file like expected. My answer isn’t necessarily the end all be all, but I do think it’s a little less hokey.

I was given my idea thanks to chatoicjava.com. By making use of the same library used for JPS (a command line tool bundled with the JDK used to monitor running instances of the JVM), you can iterate through running Java Applications and verify if there’s one running that matches whatever pattern you specify. If the command line used to launch a particular program in the JVM, the class name of the entry point for that program, the name of the jar file used to launch the program, or another criteria you specify, matches criteria used to distinguish your application then you can have your application quit immediately.

The library being used is tools.jar . You should find it in the installation dir of your JDK. At least, it should be there if you’re using the Oracle/Sun JDK. It adds 3.5MB to your project, but personally, I think it’s worth it. I found it works on OSX, XP, and Windows 7.

int counter = 0; /* * http://chaoticjava.com/posts/retrieving-a-vms-pid-and-more-info-through-java/ * adds about 3.5MB to the application, but small enough overall that I think * it's worth it to verify we only have one running instance */ System.out.println("Verify if another running instance is active. "); try < //get monitored host for local computer MonitoredHost host = MonitoredHost.getMonitoredHost(new String("localhost")); //System.out.println(host.getHostIdentifier()); //System.out.println(host.activeVms()); int pid; MonitoredVm vm; String vmClass; String vmCmdLine; //iterate over pids of running applications on this host. //seems every application is considered an instance of the 'activeVM' for(Object activeVMPid : host.activeVms()) < pid = (Integer)activeVMPid; System.out.println("Looking at pid: " + pid); //get specific vm instance for given pid vm = host.getMonitoredVm(new VmIdentifier("//" + pid)); //get class of given vm instance's main class vmCmdLine = MonitoredVmUtil.commandLine(vm); vmClass = MonitoredVmUtil.mainClass(vm, true); //is class in vm same as class you're comparing? System.out.println("class to examine: [" + vmClass + "]"); System.out.println("cmd line to examine: [" + vmCmdLine + "]"); if(vmClass.equals(myClass.class.getName()) || vmClass.equals("myJar.jar") || ( vmCmdLine.contains("myJar.jar") || vmCmdLine.contains(myClass.class.getSimpleName()) )) < counter++; System.out.println("Match to current class"); >> System.out.println("Found running instances of this " + "program (including this one): " + counter); System.out.println("Runtime info of this class: " + ManagementFactory.getRuntimeMXBean().getName()); > catch (Exception e) < e.printStackTrace(); >if(counter > 1) < System.out.println("Attempting to run more than " + "one instance. Exiting."); System.exit(-1); >else

Источник

Оцените статью