2014-08-29 61 views
1

我正在开发Java应用程序。我想阻止用户同时运行同一个Java应用程序的更多实例。我使用Java的JUnique应用程序锁定库,它效果很好。但是当它崩溃时会遇到一个严重的问题。如果应用程序崩溃,JUnique锁定的应用程序不会运行

应用程序如果崩溃就无法启动,它只是返回AlreadyLockedException。下面是我用来锁定我的应用程序的代码。

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; 
} 

和代码来释放我的锁是:

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

我可以使用release()方法来处理预期的崩溃。但真正的问题发生在运行时应用程序意外崩溃。应用程序终止而不释放获取的应用程序锁。

如果应用程序意外崩溃,我们该如何释放JUnique锁定?

+0

定义“崩溃”。该文档声明锁定“将在JVM暂停时自动释放”。另外,打印并发布该'AlreadyLockedException'的堆栈跟踪。 – chrylis 2014-08-29 08:47:19

+2

您可以尝试注册['Thread.UncaughtExceptionHandler'](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html) – MadProgrammer 2014-08-29 08:58:11

+0

@chrylis,这就是它释放锁,但如果其他程序也在运行JVM,那么JVM不会停止。即使我的应用程序崩溃,锁仍然会存在于JVM中。 – Crawler 2014-08-29 10:02:46

回答

3

这是JUnique的设计缺陷(最新版本,我发现here)。根本不支持电脑死机的用例(BSOD,电源中断)。假定总是执行ShutdownHook(它删除锁,请参阅JUnique.java)。这个漏洞在releaseLock api-docs:

中显而易见:“请注意,一个锁只能由先前获得它的同一个JVM重新销售,如果给定的ID不对应于属于目前的JVM,不会采取任何行动。“

但是没有方法forceReleaseLock(String id)这反过来意味着在计算机崩溃后应用程序不能再启动了。

在这种情况下,向用户显示消息“应用程序已经运行”和显示正在运行的应用程序的窗口的“确定”按钮是很常见的。在这种情况下,你可以添加一个按钮“不,它不是”,并点击时:

  • 检查应用程序没有打开的窗口。
  • 检查JUnique.sendMessage返回null。
  • 删除new File(System.getProperty("user.home"), ".junique");的内容(LOCK_FILES_DIR,请参阅JUnique.java)或类似的粗糙度较低的内容。
  • 启动应用程序。
+0

我编辑了答案并添加了解决我的问题的一些代码。感谢vanOekel。 @MadProgrammer感谢您的建议。 – Crawler 2014-09-04 11:13:14

+0

@Crawler我不认为增加一个'UncaughtExceptionHandler'可以改善任何事情:由JUnique注册的'ShutdownHook'已经确保在应用程序/ JVM停止(没有崩溃)之前移除锁。 – vanOekel 2014-09-04 16:57:27

+0

在我的情况下,当应用程序崩溃时,JUnique锁不会被释放,所以我必须在UncaughtExceptionHandler内部显式调用releaseLock()。如果我的应用程序崩溃,我不想停止JVM。最后,通过调用uncaughtException方法,未捕获的异常在关闭钩子中以与任何其他线程相同的方式处理。你的信息很好,但UncaughtExceptionHandler做到了。 – Crawler 2014-09-04 17:13:17