2014-08-29 65 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