一度Javaプログラムのインスタンスを1つだけ実行することを可能にする方法?

StackOverflow https://stackoverflow.com/questions/920386

  •  06-09-2019
  •  | 
  •  

質問

私は自分のJavaアプリケーション(WebStartのスイングアプリ)を複数回起動からユーザーを防ぐために必要です。アプリケーションが既に警告を再起動するか、を示すことが可能であるべきではない実行しているのであれば/再び閉鎖されます。

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

ところで。ターゲットプラットフォームは、Java 1.5を使用してWindows XPです。

役に立ちましたか?

解決

私はあなたのアプリケーションを起動したときに聞くためにポートを開くあなたの提案が最高のアイデアだと思います。

これを行うのは非常に簡単だとあなたはあなたのアプリケーションを閉じたときに、それをクリーンアップを心配する必要はありません。あなたはファイル誰かに書き込む場合たとえば、そのファイルは削除されません。

タスクマネージャを使用してプロセスを強制終了 私の記憶が正しければ、

また、そうしようとすると、PIDを使用して解決策を策定していないJVM内部からJavaプロセスの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に結合ます。

ポートを選ぶときは、

ウェルノウンポートのリストに記載されたものを回避しようとする 。あなたが理想的なポートがファイルまたは紛争の場合は、コマンドラインスイッチを経由して、設定を使用するべきである。

他のヒント

質問はWebStartのが使用されていると述べているとおり、

、明白な解決策は、<のhref = "http://java.sun.com/javase/6/docs/jre/api/javaws/jnlp/javax/を使用することですJNLP / SingleInstanceService.html」のrel = "noreferrer"> javax.jnlp.SingleInstanceService でます。

このサービスは、1.5で利用可能です。 1.5は寿命期間の終わりを通じて、現在の方法のほとんどをであることに注意してください。 Java SEの6!で取得します。

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

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

ファイルロックを行う方法の例は、Java開発者の年鑑

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

私は、Javaプログラマではないので、私はあなたがJavaでのものと同じ種類の操作を行うことができるかどうかわからないのですか?

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

のhttp://rumatoest.blogspot .COM / 2015/01 / HOWTO-実行する専用の単一の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する

これは気乗りせずJavaなどの高級言語を使用しての目的に反しものの、

あなたは、レジストリを使用することができます。少なくとも、あなたのターゲットプラットフォームは、Windowsで= D

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

私はこの質問のように多くのを見てきましたし、私は、ファイアウォールと衝突またはソケットのものに入るためにチャンスを取ることはありませんプラットフォームに依存しない方法で同じ問題を解決するために探していた。

だから、ここで私がやったことだ。

import java.io.File;
import java.io.IOException;

/**
 * This static class is in charge of file-locking the program
 * so no more than one instance can be run at the same time.
 * @author nirei
 */
public class SingleInstanceLock {

    private static final String LOCK_FILEPATH = System.getProperty("java.io.tmpdir") + File.separator + "lector.lock";
    private static final File lock = new File(LOCK_FILEPATH);
    private static boolean locked = false;

    private SingleInstanceLock() {}

    /**
     * Creates the lock file if it's not present and requests its deletion on
     * program termination or informs that the program is already running if
     * that's the case.
     * @return true - if the operation was succesful or if the program already has the lock.<br>
     * false - if the program is already running
     * @throws IOException if the lock file cannot be created.
     */
    public static boolean lock() throws IOException {
        if(locked) return true;

        if(lock.exists()) return false;

        lock.createNewFile();
        lock.deleteOnExit();
        locked = true;
        return true;
    }
}

ロックファイルパスにはSystem.getProperty(「java.io.tmpdirの」)を使用すると、常に同じ場所であなたのロックを作成することを確認します。

次に、あなたのプログラムからあなただけのようなものを呼び出します:

blah blah main(blah blah blah) {
    try() {
        if(!SingleInstanceLock.lock()) {
            System.out.println("The program is already running");
            System.exit(0);
        }
    } catch (IOException e) {
        System.err.println("Couldn't create lock file or w/e");
        System.exit(1);
    }
}

そして、それは私のためにそれをしません。さて、あなたがプログラムを殺す場合には、ロックファイルを削除しませんが、そのプロセスがすでに実行されている場合は、ロックファイルの中に、プログラムのPIDを書き込み、ロック()メソッドのチェックをすることによってこの問題を解決することができます。これは、興味のある人のためassingmentとして残されています。 :)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top