2016-04-03 16 views
0

Linuxで動作している私のJavaプログラムは、シャットダウンする前にいくつかのファイルハンドル(実際にはデバイス)を閉じる必要があるため、JVMにシャットダウンフックが追加されています。しかし、java.util.logging.LogManagerにもシャットダウンフックがあり、シャットダウンする前にシャットダウンする傾向があり、シャットダウンプロセスについて何もログに記録できないことに気付きました。`java.util.logging.LogManager`のシャットダウンが早すぎるのを防ぐことができますか?

シャットダウン中にログを実行できるようにLogManagerがシャットダウンフックをインストールしないようにする方法はありますか?準備ができたらクリーンアップするよう教えてください。

答えて

0

ええ、システムプロパティ "java.util.logging.manager"を作成したクラスの名前で定義することができます。それはあなた自身の告発のロギングマネージャーを使用することができます。

https://docs.oracle.com/javase/8/docs/api/java/util/logging/LogManager.html

私はそれが動作しますどれだけか、それができるでしょうどれだけの仕事を知らないので、私はしかし、前にこれを試したことがありません。

+0

私はこれを考慮しましたが、それは多くの作業であるように見えます。 LogManagerのサブクラス化は理想的ですが、デフォルトのコンストラクタはシャットダウンフックが追加された場所で、呼び出されることを防ぐ手段はありません。 – tyrel

+0

時にはクラスを再実装するためにJava APIからコード全体をコピーしてから、必要な部分を修正しました。それはかなりではありませんが、それは動作します。 – markspace

+0

ええ、JDKのソースコードライセンスが私にそれを許可するかどうかは不明です。 – tyrel

1

これは回避策ですが、Linux(特定のシステム専用のプログラム)で動作しているので、sun.misc.Signalを使用してシグナルハンドラを使用しました。シグナルハンドラは、の前に実行され、のJVMがシャットダウンフックを実行します(おそらく、そのプロセスを開始する独自のシグナルハンドラもあります)。

ので、代わりのRuntime.getRuntime().addShutdownHook私は今これをやっている:

private void installSignalHandlers() { 
    SignalHandler signalHandler = signal -> shutDown(); 
    Signal.handle(new Signal("INT"), signalHandler); 
    Signal.handle(new Signal("TERM"), signalHandler); 
} 

素晴らしい動作するようです。私は、ログがまだ動作している間に、開いているハンドルなどを全て閉じて、shutDownに入れることができます。

0

LogManagerクリーナースレッドをシャットダウンフックに結合するか、カスタムハンドラをインストールしてファイルを直接クリーンアップします。クリーナー・スレッドは、ロガーを順番に列挙し、接続されたハンドラーをクローズしようとします。あなたのハンドラが閉じようとする最初のハンドラである限り、あなたはクリーナーがいつ実行するかを制御することができます。

public class ShutdownHandler extends Handler { 

    public static void main(String[] args) { 
     install(); 
    } 

    private static void install() { 
     LogManager lm = LogManager.getLogManager(); 
     Logger first = null; 
     ShutdownHandler sh = new ShutdownHandler(); 
     for (;;) { 
      try { 
       Enumeration<String> e = lm.getLoggerNames(); 
       while (e.hasMoreElements()) { 
        first = lm.getLogger(e.nextElement()); 
        if (first != null) { 
         break; 
        } 
       } 
       break; 
      } catch (ConcurrentModificationException olderJvm) { 
      } 
     } 

     Logger.getLogger("").addHandler(sh); 
     if (first != null) { 
      first.addHandler(sh); 
     } 
    } 

    public ShutdownHandler() { 
     super.setLevel(Level.ALL); 
    } 

    @Override 
    public void publish(LogRecord record) { 
    } 

    @Override 
    public void flush() { 
    } 

    @Override 
    public void close() throws SecurityException { 
     if (!Level.OFF.equals(super.getLevel())) { 
      super.setLevel(Level.OFF); 
      shutDown(); 
     } 
    } 

    private void shutDown() { 
     System.out.println(this + " shutdown by " 
       + Thread.currentThread().getClass().getName()); 
     //Close your files or join with your other shutdown hook. 
    } 
} 
関連する問題