• ベストアンサー

シャットダウンフックが呼ばれない

Runtime#addShutdownHook(...) を利用して、 PCのシャットダウン時刻をファイルに保存するプログラムを作成しています。 ところが、Windowsのログオフやシャットダウンを選択しても、シャットダウンフックが呼ばれないことがあります。 OS Windows XP SP2 JVM Sun 1.4.2_08-b03 ただし、該当のプログラムを java で起動したときは正しくシャットダウンフックが呼ばれて、終了時刻が保存されています。 javawで起動したときだけシャットダウンフックが無視されます。 コンソールやウィンドウを表示させずに動かしたいのでjavawにしたのですが、何かいい方法はないでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.1

 こんばんは。 >java で起動したときは正しくシャットダウンフック >が呼ばれて、終了時刻が保存されています。 >javawで起動したときだけシャットダウンフックが >無視されます。  試してみたら、確かにjavawではシャットダウンフックが呼ばれませんねぇ。  でも、FrameやJFrameを使ったGUIアプリケーションの場合は呼ばれているみたいです。  あてずっぽうなんですが、javawではイベントディスパッチスレッドの有無が関係してシャットダウンフックが呼ばれたり呼ばれなかったりするんじゃないでしょうか。  こうすると↓javawでもシャットダウンフックが呼ばれるみたいです。  ちなみにJ2SE 1.5.0_02 で試しました。 import java.util.*; import java.io.*; public class ShutdownHookTest {   public static void main(String[] args) {     Runtime.getRuntime().addShutdownHook(new Thread() {       public void run() {         PrintWriter pw = null;         try {           pw = new PrintWriter(new FileWriter("log.txt", true));           pw.println(new Date());         }         catch (IOException ex) {}         finally {           if (pw != null)             pw.close();         }       }     });          java.awt.Frame frame = new java.awt.Frame();     frame.pack();     //↑Frameを表示させずに、イベントディスパッチスレッドを動かすためのpack()     //ここをコメントアウトするとシャットダウンフックがかからない。          try {       while (true) {         Thread.sleep(10000);       }     }     catch (InterruptedException ex) {}   } }  しかし、回避策とは言え、表示させもしないFrameを作るのはなんともかっこ悪いです。  やはり、コマンドプロンプトを表示させずにjava.exeを呼ぶことを考えたほうがいいのかもしれません。  でも、いい方法が思いつきません。  それにしても、この症状はJVMのバグなんでしょうか?  それとも仕様なんでしょうか?  変ですね。

その他の回答 (3)

  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.4

javawとShutdownHookで検索するとそれらしいネタが(^^; まとめると、Windowsではウィンドウの終了時(多分ログオフ時も一緒)に 終了してよいかどうかの問い合わせメッセージを「ウィンドウ」に対して行うので、 コンソールを持たないjavawではそのメッセージを受け取れず、 shutdownHookが呼び出されない、ということになります。 なので、javawを使うのであればRuntime#addShutdownHook以外の方法を考える しかなさそうですね。 #GUIがある場合は、addShutdownHookでも大丈夫そうですが。 対策としてはちょっと思いつきません。 #C++でWindowsのネイティブプログラムを組めば何とかなりそうですケド・・・

thamansa
質問者

お礼

ありがとうございます。 ちゃんと検索せずに質問してしまってすみません。

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.3

 またまた、訂正です。  よく考えたら、最後の try {   while (true) {     Thread.sleep(10000);   } } catch (InterruptedException ex) {}  これは必要なかったですね。  せっかくイベントディスパッチスレッドを動かしたんだから、何もメインスレッドまでぐるぐる待機させる必要なかったです。  たびたび、すみません。

thamansa
質問者

お礼

ありがとうございます。 コンソールもGUIも無いと終了するのに困ってしまうので、とりあえずタスクトレイにアイコン表示して、SWTのaddDisposeListener()で終了時のイベントハンドラを使うようにして解決できました。

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.2

 すみません。  ちょっと訂正です。 >試してみたら、確かにjavawではシャットダウンフックが呼ばれませんねぇ。    ↓ 試してみたら、確かにjavawではWindowsのログオフやシャットダウンではシャットダウンフックが呼ばれませんねぇ。  プログラム自身が終了する場合では、javawでもシャットダウンフックが呼ばれるのは、こちらでも確認できまた。

関連するQ&A