
SwingでスタンドアロンのJavaプログラムを作成しています。
Executable JARファイルとして、ダブルクリックにより起動するのですが、一度起動した後もう一度ダブルクリックすると同じプログラムが別に起動してしまいます。
JDK1.5、OSはWindowsが対象です。
複数起動できないようにする方法はありますでしょうか?
よろしくお願いします。
※ファイルに起動フラグを書出すという方法は考えてみましたが、クラッシュ(異常終了)したときに起動不可能になるためこの方法は使用できませんでした。
No.2ベストアンサー
- 回答日時:
私が思いつく一般的と思われる方法は2つあります。
(1)WindowsのMutexを利用する方法
WinAPIのCreateMutex()を利用し、適当な名前のMutexを作成します。
Mutex作成の成功・失敗でプログラムの二重起動を判定します。
Windowsでは一般的な方法ですので情報は手に入れやすいと思います。
ただし、Java以外の言語でプログラムを書く必要があります。
(2)ファイルチャネルのロックを利用する方法
あくまでJavaのみでということでしたら、ファイルチャネルのロックを利用する方法があります。
説明しにくいのでサンプルコードを書きます。(あくまでサンプルなので、実際に使う場合はよくテストしてください。)
仮にVMが異常終了した場合でもロックはおそらく開放されます。(Windowsがプロセスの終了を検知するため)
万が一開放されなかった場合でも、Windowsの再起動で開放されます。
--------------------------------------------------------------------------------
import java.io.File;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class Sample {
public static void main(String[] args) {
//起動チェック
final FileOutputStream fos = new FileOutputStream(new File("lock"));
final FileChannel fc = fos.getChannel();
final FileLock lock = fc.tryLock();
if (lock == null) {
//既に起動されているので終了する
return;
}
//ロック開放処理を登録
Runtime.getRuntime().addShutdownHook(
new Thread() {
public void run() {
if (lock != null && lock.isValid()) {
lock.release();
}
fc.close();
fos.close();
}
}
);
//処理を続行
}
}
--------------------------------------------------------------------------------
それから、#1さんのソケットを使う方法には以下の問題点があります。
・メッセージの送受信(起動チェック)とリスン開始(ロック)の処理が分離されている (タイミング次第で多重起動可能)
・起動されていない場合(正常系)と何らかのエラーで返信が返ってこない場合(異常系)の区別ができない
・返信が無いというのはタイムアウトになるということであり、起動時間が多少長くなる
個人用のツールならともかく、業務システムに使用するのはお勧めできません。
#念の為に書いておきますが、回答を批判しているわけではありません。
ご回答ありがとうございます。
今回は、「(2)ファイルチャネルのロックを利用する方法」を使わせていただきます。
java.util.logging.Loggerを使っていて、ファイルのロックの例はすぐ目の前にあったのですが、重複起動チェックに使用することまでは気付きませんでした。
タスクマネージャーでJavaプログラム起動中にjavaw.exeプロセスを終了する確認などもしてみました。
今のところ、この方法で特に問題はなさそうです。
非常に助かりました。ありがとうございました。
No.1
- 回答日時:
>※ファイルに起動フラグを書出すという方法は考えてみましたが、
>クラッシュ(異常終了)したときに起動不可能になるためこの方法は使用
>できませんでした。
ならば、ソケット通信を使って、二重起動を監視してみてはいかがでしょうか?
アプリケーション起動時にソケット通信を使って、他のアプリケーションへ
メッセージを送信する。送信メッセージに対する返信がなければ、自分しか
起動されていないのでOK。返信があればNG。
自分しか起動されていないことがわかったら、次に、他のアプリケーションが
二重起動されるのを防ぐために、決められたポート番号でリスンする。
このポート番号に他のアプリケーションからメッセージが送信されてきた場合は、
既に起動済みである旨のメッセージを返す。
ただし、気をつけなければならないのは、決められたポートでリスンする処理は、
アプリのメインスレッドとは別のスレッドで行う必要があるということです。
ご回答ありがとうございます。
今回はNo.2にgimmickさんから頂いた回答の「(2)ファイルチャネルのロックを利用する方法」を使うことにしました。
ソケット通信を使うことまでは気付きませんでした。
将来、別の機会に使うこともあるかもしれないので、動作確認のために実装を試みてみました。
その結果分かったことは、リスンのためにServerSocketでポートを開こうとすると、WindowsXP SP2の「Windowsファイアウォール」でブロックされてしまう場合もありそうです。
※もしかしたらローカルホストに限定すればブロックされないのかもしれませんが、まだ深くは追求していません。
おかげ様で、問題解決方法の視野を広げることができました。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
先着1,000名様に1,000円分もらえる!
教えて!gooから感謝をこめて電子書籍1,000円分プレゼント
-
生成したインスタンスを削除する方法
Java
-
Log4jで機能毎に別ファイルへ出力する方法
Java
-
Java 特定プロセス名前取得方法について
Java
-
4
プログラムの二重起動防止
Java
-
5
バッチファイルで多重起動を防ぐ
その他(プログラミング・Web制作)
-
6
(Swing)JTextFieldを半角のみ入力可能にする方法
Java
-
7
Javaで自分のプロセスIDが取得したい
Java
-
8
jFrameを使って複数の画面を生成するにはどうすれば良いのでしょうか?
Java
-
9
JavaのSwingで別のフォームを閉じる方法
Java
-
10
ボタンの複数割り当てについて
Java
-
11
windows 環境でのファイル操作について
Java
-
12
JTextFieldの入力制限
Java
-
13
timestampのデータはどのようにして入力
PostgreSQL
-
14
画面を隠す・消す方法を教えてください。
Java
-
15
Windowsのログオフしないで、ネットワークだけログオフしたい
セキュリティホール・脆弱性
-
16
shellからストアドプロシージャの呼び出し
Oracle
-
17
Jtableの特定のセルの背景色や文字色について
Java
関連するQ&A
- 1 Swingアプリ→Servletプログラムの起動方法
- 2 Javaのswingについて質問です。 CUIのときだと前からプログラムを処理していきすべて終われば
- 3 Javaでプログラムをコマンドから「プログラム名」だけで起動できる?
- 4 javaのプログラムについてです。(Swingを使っています)
- 5 複数のJavaプログラムでデータを共有する方法について
- 6 10進の自然数を2進数に変換するプログラム(jav
- 7 JavaのSwingで別のフォームを閉じる方法
- 8 マインクラフトはforgeとJavaがないと起動出来ないんですか?それとも、Javaのみで起動出来ま
- 9 Javaでユーザーが設定した外部プログラムの起動
- 10 Javaのプログラムから外部のソフトウェアやコマンドプロンプトを起動・
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
人気Q&Aランキング
-
4
Tomcatのシャットダウンについて
-
5
リモートからTomcatにアクセス...
-
6
Apache Tomcat 起動エラー
-
7
Eclipse + JBOSS でのデバッグ
-
8
Tomcatでwarファイルの展開に失...
-
9
EclipseからTomcatを起動した際...
-
10
tomcatをプロジェクト毎に起動...
-
11
JavaServletデバッグってどうや...
-
12
javaサーブレットから別サーバ...
-
13
eclipseからweblogic起動
-
14
GRAPHS32.OCX
-
15
tomcatの再起動とApacheの設定...
-
16
「ファイルが見つかりません D...
-
17
Eclipse開発時workディレクトリ...
-
18
Tomcatプロジェクトの.properti...
-
19
GCログに日付時刻を表示したい
-
20
Eclipseのアンインストールの仕方
おすすめ情報