防止启动Java应用程序的多个实例

Sat*_*ish 21 java runtime executable-jar

我想阻止用户多次并行运行我的java应用程序.

为了防止这种情况,我在打开应用程序时创建了一个锁定文件,并在关闭应用程序时删除了锁定文件.

当应用程序运行时,您无法打开另一个jar实例.但是,如果通过任务管理器终止应用程序,则不会触发应用程序中的窗口关闭事件,也不会删除锁定文件.

如何确保锁定文件方法有效或我可以使用其他机制?

Man*_*uel 13

您可以使用 FileLock,这也适用于多个用户共享端口的环境:

String userHome = System.getProperty("user.home");
File file = new File(userHome, "my.lock");
try {
    FileChannel fc = FileChannel.open(file.toPath(),
            StandardOpenOption.CREATE,
            StandardOpenOption.WRITE);
    FileLock lock = fc.tryLock();
    if (lock == null) {
        System.out.println("another instance is running");
    }
} catch (IOException e) {
    throw new Error(e);
}
Run Code Online (Sandbox Code Playgroud)

也幸免于垃圾收集。一旦您的进程结束,锁就会被释放,无论是正常退出还是崩溃或其他什么。


Sap*_*Sap 12

类似的讨论见 http://www.daniweb.com/software-development/java/threads/83331

绑定ServerSocket.如果它无法绑定,则中止启动.由于ServerSocket只能绑定一次,因此只能运行程序的单个实例.

在你问之前,没有.仅仅因为绑定了ServerSocket,并不意味着您对网络流量开放.只有在程序开始用accept()监听端口时才会生效.

  • PSA:服务器套接字工作得很好,只是不要忘记将它分配给在进程的生命周期内不会被垃圾收集的东西,否则排除好处将是短暂的(或者更糟的是,它会工作得足够长让你想知道它停止时发生了什么)。 (2认同)

sgi*_*bly 7

我看到你可以尝试两个选项:

  1. 使用Java 关闭钩子
  2. 让您的锁文件保存主进程号.当您浏览另一个实例时,该过程应该存在.如果在您的系统中找不到它,您可以认为可以解除锁定并覆盖锁定.


dav*_*xxx 5

创建服务器套接字,在应用程序启动时使用ServerSocket实例绑定到特定端口是一种直接的方法。
请注意ServerSocket.accept()阻塞,因此在其自己的线程中运行它是有意义的,不要阻塞 main Thread

这是一个检测到抛出异常的示例:

public static void main(String[] args) {       
    assertNoOtherInstanceRunning();
    ...     // application code then        
}

public static void assertNoOtherInstanceRunning() {       
    new Thread(() -> {
        try {
            new ServerSocket(9000).accept();
        } catch (IOException e) {
          throw new RuntimeException("the application is probably already started", e);
        }
    }).start();       
}
Run Code Online (Sandbox Code Playgroud)