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

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

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

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

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

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

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

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

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

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

您可以将创建锁文件的进程的进程ID写入文件。 当您遇到现有的锁文件时,您不仅要退出,还要检查具有该ID的进程是否仍然存在。 如果没有,你可以继续。

您可以创建一个服务器套接字

new ServerSocket(65535, 1, InetAddress.getLocalHost()); 

在你的代码的最开始。 然后,如果在主块中捕获到AddressAlreadyInUseexception,则可以显示相应的消息。

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

以下是检测到exception抛出的示例:

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

..我可以使用其他机制吗?

如果应用程序。 有一个GUI,它可以使用Java Web Start启动 。 提供给web-start的JNLP API提供SingleInstanceService 。 这是我的演示。 SingleInstanceService

你可以写这样的东西。

如果文件存在,请尝试删除它。 如果它无法删除。 我们可以说应用程序已在运行。

现在再次创建相同的文件并重定向sysout和syserr。

这对我有用

您可以使用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); } 

还存在垃圾收集。 一旦您的过程结束,锁定就会被释放,无论是经常退出还是崩溃等都无关紧要。

File类中已经有可用的java方法来实现相同的function。 方法是deleteOnExit(),它确保在JVM退出时自动删除文件。 但是,它不适合强行终止。 在强行终止的情况下,应该使用FileLock。

有关详细信息, 请访问https://docs.oracle.com/javase/7/docs/api/java/io/File.html

因此,可以在main方法中使用的代码片段可以是:

 public static void main(String args[]) throws Exception { File f = new File("checkFile"); if (!f.exists()) { f.createNewFile(); } else { System.out.println("App already running" ); return; } f.deleteOnExit(); // whatever your app is supposed to do System.out.println("Blah Blah") }