web-dev-qa-db-ja.com

Javaプログラムのインスタンスを一度に1つだけ実行できるようにするにはどうすればよいですか?

ユーザーがJavaアプリケーション(WebStart Swingアプリ)を複数回起動しないようにする必要があります。したがって、アプリケーションがすでに実行されている場合は、再度起動したり、警告を表示したりすることはできません。再び閉じました。

これを達成するための便利な方法はありますか?ポートをブロックするか、sthをファイルに書き込むことを考えました。しかし、うまくいけば、いくつかのシステムプロパティまたはJVMにアクセスできますか?

ところで。ターゲットプラットフォームはWindows XP with Java 1.5

27
räph

アプリケーションを起動するときにリッスンするポートを開くという提案が最善のアイデアだと思います。

これは非常に簡単で、アプリケーションを閉じるときにクリーンアップすることを心配する必要はありません。たとえば、ファイルに書き込んだ後、誰かがタスクマネージャを使用してプロセスを強制終了した場合、ファイルは削除されません。

また、私が正しく覚えていれば、JVM内からJavaプロセスのPIDを取得する簡単な方法はないので、PIDを使用してソリューションを作成しようとしないでください。

このような何かがトリックを行う必要があります:

private static final int PORT = 9999;
private static ServerSocket socket;    

private static void checkIfRunning() {
  try {
    //Bind to localhost adapter with a zero connection queue 
    socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
  }
  catch (BindException e) {
    System.err.println("Already running.");
    System.exit(1);
  }
  catch (IOException e) {
    System.err.println("Unexpected error.");
    e.printStackTrace();
    System.exit(2);
  }
}

このサンプルコードは明示的に127.0.0.1にバインドします。これにより、このアドレスのトラフィックはローカルシステムからのものである必要があるため、ファイアウォールの警告を回避できます。

ポートを選択するときは、 既知のポートのリスト に記載されているポートを避けるようにしてください。理想的には、競合が発生した場合に、使用するポートをファイル内またはコマンドラインスイッチを介して構成可能にする必要があります。

35
Dave Webb

質問にはWebStartが使用されていると記載されているため、明らかな解決策は javax.jnlp.SingleInstanceService

このサービスは1.5で利用できます。 1.5は現在、耐用年数の終わりのほとんどの期間であることに注意してください。 Java SE 6!

26

私はより良い考えはファイルロックを使うことだと思います(かなり古い考え:))。 Java 1.4以降、ファイルロックを可能にする新しいI/Oライブラリが導入されました。

アプリケーションが起動すると、ファイルのロックを取得しようとします(または、存在しない場合はファイルを作成します)。アプリケーションが終了すると、ロックが解除されます。アプリケーションがロックを取得できない場合、アプリケーションは終了します。

ファイルロックを行う方法の例は、たとえば Java Developers Almanac にあります。

Java Web Startアプリケーションまたはアプレットでファイルロックを使用する場合は、アプリケーションまたはアプレットを歌う必要があります。

3

C++でも、カーネルミューテックスオブジェクトを作成し、起動時にそれを探すことで同じことを行います。利点は、ソケットを使用する場合と同じです。つまり、プロセスが停止/クラッシュ/終了/強制終了されると、ミューテックスオブジェクトがカーネルによってクリーンアップされます。

私はJavaプログラマーではないので、Javaで同じようなことができるかどうかわかりませんか?

1
Colin Desmond

JUniqueライブラリを使用できます。シングルインスタンスJavaアプリケーションの実行をサポートし、オープンソースです。

http://www.sauronsoftware.it/projects/junique/

単一インスタンスを実装する方法Javaアプリケーション? )の私の完全な回答も参照してください。

1
kolobok

クロスプラットフォームのAppLockクラスを作成しました。

http://rumatoest.blogspot.com/2015/01/howto-run-only-single-Java-application.html

ファイルロック技術を使用しています。

更新。 2016-10-14に、maven/gradleと互換性のあるパッケージを作成しました https://github.com/jneat/jneat そしてここで説明しました http://rumatoest.blogspot。 com/2015/06/synchronize-code-over-multiple-jvm.html

1
rumatoest

レジストリを使用することもできますが、これはJavaのような高級言語を使用するという目的を中途半端に無効にします。少なくともターゲットプラットフォームはwindows = D

0
codebliss

JUniqueをお試しください:

String appId = "com.example.win.run.main";
boolean alreadyRunning;
try {
    JUnique.acquireLock(appId);
    alreadyRunning = false;
} catch (AlreadyLockedException e) {
    alreadyRunning = true;
}
if (alreadyRunning) {
    Sysout("An Instance of this app is already running");
    System.exit(1);
}
0