JUnique 1.0 manual
The JUnique library can perform cross-JVM lock operations. It is mainly intended to prevent a user to run simultaneously more instances of the same Java application, and it also offers a communication layer enabling message exchange between different JVMs.
JUnique is based on a user related cross-JVM exclusive lock concept. Suppose you want to avoid your Java desktop application to be started more than once by the same user. When the main() method of your application is called, you can require to JUnique a lock on a certain ID, i.e. myapplicationid. At the first application launch that ID will be surely available, and so the lock will be taken. The obtained lock can be explicitly released with a JUnique.releaseLock() call, otherwise it will be automatically released when JVM halts. If another JVM instance (or even the same one) will try to impose a lock on the same ID, JUnique will return with an AlreadyLockedException, notifying the instance that another one is currently running. Then the second instance can choose to abort its start sequence, and optionally it can send one or more messages to the active one before exiting.
Please note that a JUnique lock is user-related: two different users accessing the system at the same time can still run two separate instances of the same application, since JUnique IDs reside in a user scope.
Requirements
To run the JUnique library you need a Java Runtime Environment J2SE v. 1.4 or later.
Installation
Add the JUnique JAR file to your application classpath, and you'll be automatically enabled to the use of the JUnique classes.
Javadocs
Here come the JUnique javadocs.
Quickstart
A sample main() method preventing multiple running instances of the same application for the same user:
public static void main(String[] args) { String appId = "myapplicationid"; boolean alreadyRunning; try { JUnique.acquireLock(appId); alreadyRunning = false; } catch (AlreadyLockedException e) { alreadyRunning = true; } if (!alreadyRunning) { // Start sequence here } }
A message handling example, transfering arguments from the aborting instance to the active one:
public static void main(String[] args) { String appId = "myapplicationid"; boolean alreadyRunning; try { JUnique.acquireLock(appId, new MessageHandler() { public String handle(String message) { // A brand new argument received! Handle it! return null; } }); alreadyRunning = false; } catch (AlreadyLockedException e) { alreadyRunning = true; } if (!alreadyRunning) { // Start sequence here } else { for (int i = 0; i < args.length; i++) { JUnique.sendMessage(appId, args[0])); } } }
Lock ID strategies
To avoid potential conflicts, it is advisable to choose a fully qualifying lock ID for each application using JUnique. Using a generic ID, such "notepad", "chat" or "myapp", is not a good idea. Better to use something like "myName.myAppName", and even better it's to pick your application main class full name as the JUnique lock ID.