1

I'm developing a Java application. And I wanted to prevent a user to run simultaneously more instances of the same Java application. I used JUnique app locking library for Java and it works great. But has a serious issue when it crashes.

The application cannot be started if it crashes, it just returns AlreadyLockedException. The code I used to lock my application is below.

public static boolean isRunning() {
    boolean alreadyRunning = false;
    try {
        JUnique.acquireLock(appId);
        alreadyRunning = false;
    } catch (AlreadyLockedException e) {
        logger.error("Unable to acquire lock. There is an instance already running");
        alreadyRunning = true;
    } catch (Throwable t) {
        logger.error("Unable to acquire lock. ", t);
    }
    return alreadyRunning;
}

And code to release my lock is:

public static void release() {
    try {
        JUnique.releaseLock(appId);
    } catch (Throwable t) {
        logger.error("Error releasing the lock", t);
    }
}

I can use release() method for dealing with expected crashes. But the real problem occurs when application crashes unexpectedly during runtime. The application is terminated without releasing the acquired lock for application.

How can we release JUnique lock if the application unexpectedly crashes?

Crawler
  • 1,988
  • 3
  • 21
  • 42
  • Define "crashes". The documentation states that the lock "will be automatically released when JVM halts". Also, print and post the stack trace of that `AlreadyLockedException`. – chrylis -cautiouslyoptimistic- Aug 29 '14 at 08:47
  • 2
    You try registering a [`Thread.UncaughtExceptionHandler`](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html) – MadProgrammer Aug 29 '14 at 08:58
  • @chrylis, thats right it release the lock, but what if other program also is running JVM then JVM wont halt. Even if my app crash, lock will still be there in JVM. – Crawler Aug 29 '14 at 10:02
  • What do you mean by "other program"? It sounds like you don't understand how Java program launching works. – chrylis -cautiouslyoptimistic- Aug 29 '14 at 10:04
  • @chrylis, i knw how java program works. When I run my application and if it crashes, it halts JVM and there is no problem in running new instance again. But if my application crashes when I'm using ecilpse, it somehow keeps locking alive in JVM because Eclipse is still using JVM. And application cant be started again until I close eclipse. – Crawler Aug 29 '14 at 10:22
  • If that's the case, I'd 1) look at an uncaught exception handler, and 2) file a bug against JUnique, since running inside an IDE is common enough that it ought to handle the case. – chrylis -cautiouslyoptimistic- Aug 29 '14 at 12:14

1 Answers1

4

It is a design flaw of JUnique (last version I found here). There is simply no support for the use case of a computer crash (BSOD, power interrupt). It is assumed that the ShutdownHook (which removes the locks, see JUnique.java) is always executed. The flaw is evident in the releaseLock api-docs:

"Please note that a lock can be realeased only by the same JVM that has previously acquired it. If the given ID doens't correspond to a lock that belongs to the current JVM, no action will be taken."

But there is no method forceReleaseLock(String id) which in turn means that after a computer crash, the application can no longer be started.

In these kind of cases it is quite common to present the user a dialog with a message "The application is already running" and an "OK" button that shows the window of the running application. In this case, you could add a button "No, it is not" and when clicked:

  • check that there is no open window of the application.
  • check that JUnique.sendMessage returns null.
  • delete the contents of new File(System.getProperty("user.home"), ".junique"); (the LOCK_FILES_DIR, see JUnique.java), or something similar that is less crude.
  • start the application.
vanOekel
  • 6,358
  • 1
  • 21
  • 56
  • I edited answer and added some code that solved my problem. Thanks vanOekel. @MadProgrammer thanks for your suggestion. – Crawler Sep 04 '14 at 11:13
  • @Crawler I do not think adding an `UncaughtExceptionHandler` improves anything: the `ShutdownHook` registered by JUnique already ensures a lock is removed before the application/JVM stops (without crashing). – vanOekel Sep 04 '14 at 16:57
  • in my case, JUnique lock is not released when application crashes so I've to explicitly call releaseLock() inside UncaughtExceptionHandler. And I dont want to halt JVM if my application crashes. Finally Uncaught exceptions are handled in shutdown hooks same way as in any other thread, by invoking the uncaughtException method. Your info was good but UncaughtExceptionHandler did the trick. – Crawler Sep 04 '14 at 17:13