プロが教える店舗&オフィスのセキュリティ対策術

Runtime#addShutdownHook(...) を利用して、
PCのシャットダウン時刻をファイルに保存するプログラムを作成しています。

ところが、Windowsのログオフやシャットダウンを選択しても、シャットダウンフックが呼ばれないことがあります。

OS Windows XP SP2
JVM Sun 1.4.2_08-b03

ただし、該当のプログラムを
java で起動したときは正しくシャットダウンフックが呼ばれて、終了時刻が保存されています。
javawで起動したときだけシャットダウンフックが無視されます。

コンソールやウィンドウを表示させずに動かしたいのでjavawにしたのですが、何かいい方法はないでしょうか?

A 回答 (4件)

 こんばんは。



>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のバグなんでしょうか?
 それとも仕様なんでしょうか?

 変ですね。
    • good
    • 0

javawとShutdownHookで検索するとそれらしいネタが(^^;



まとめると、Windowsではウィンドウの終了時(多分ログオフ時も一緒)に
終了してよいかどうかの問い合わせメッセージを「ウィンドウ」に対して行うので、
コンソールを持たないjavawではそのメッセージを受け取れず、
shutdownHookが呼び出されない、ということになります。

なので、javawを使うのであればRuntime#addShutdownHook以外の方法を考える
しかなさそうですね。
#GUIがある場合は、addShutdownHookでも大丈夫そうですが。

対策としてはちょっと思いつきません。
#C++でWindowsのネイティブプログラムを組めば何とかなりそうですケド・・・
    • good
    • 0
この回答へのお礼

ありがとうございます。

ちゃんと検索せずに質問してしまってすみません。

お礼日時:2005/08/05 13:09

 またまた、訂正です。



 よく考えたら、最後の

try {
  while (true) {
    Thread.sleep(10000);
  }
}
catch (InterruptedException ex) {}

 これは必要なかったですね。

 せっかくイベントディスパッチスレッドを動かしたんだから、何もメインスレッドまでぐるぐる待機させる必要なかったです。

 たびたび、すみません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

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

お礼日時:2005/08/05 13:06

 すみません。


 ちょっと訂正です。

>試してみたら、確かにjavawではシャットダウンフックが呼ばれませんねぇ。
   ↓
試してみたら、確かにjavawではWindowsのログオフやシャットダウンではシャットダウンフックが呼ばれませんねぇ。

 プログラム自身が終了する場合では、javawでもシャットダウンフックが呼ばれるのは、こちらでも確認できまた。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!