2012-12-11 14 views
6

Posiadam wyspecjalizowaną klasę rejestratora, która używa klasy java.util.logging.Logger. Chcę móc użyć tego rejestratora w haku zamknięcia innej klasy. Wydaje się jednak, że nie loguje się przy wyłączaniu. Z tego, co przeczytałem, może już być włączony hak wyłączający dla samego rejestratora, który jest przyczyną problemu.Java - Jak uzyskać rejestrator do pracy w haku zamknięcia?

Jak mogę to uruchomić? Najlepiej byłoby, gdyby było widoczne w pliku dziennika, który faktycznie wykonałem hak zamykający po zakończeniu procesu.

+0

Nie jestem pewien, czy jest to prawda, czy nie, ale nie masz kontroli nad kolejnością występowania haków zamknięcia. –

+1

To prawda, że ​​działają [jednocześnie] (http://docs.oracle.com/javase/1.5.0/docs/guide/lang/hook-design.html) –

Odpowiedz

8

Znowu patrząc na źródło, rozwiązanie wydaje się być określenie właściwości systemu java.util.logging.manager który jest podklasą LogManager który zastępuje metodę reset(); więc Przewoźnicy nadal działać na wyłączenie.

import java.util.logging.LogManager; 
import java.util.logging.Logger; 

public class Main { 
    static { 
     // must be called before any Logger method is used. 
     System.setProperty("java.util.logging.manager", MyLogManager.class.getName()); 
    } 

    public static class MyLogManager extends LogManager { 
     static MyLogManager instance; 
     public MyLogManager() { instance = this; } 
     @Override public void reset() { /* don't reset yet. */ } 
     private void reset0() { super.reset(); } 
     public static void resetFinally() { instance.reset0(); } 
    } 

    public static void main(String... args) { 
     Logger logger1 = Logger.getLogger("Main1"); 
     logger1.info("Before shutdown"); 
     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        Logger logger2 = Logger.getLogger("Main2"); 
        logger2.info("Shutting down 2"); 

       } finally { 
        MyLogManager.resetFinally(); 
       } 
      } 
     })); 
    } 
} 

drukuje

Dec 11, 2012 5:56:55 PM Main main 
INFO: Before shutdown 
Dec 11, 2012 5:56:55 PM Main$1 run 
INFO: Shutting down 2 

Od tego kodu dla LogManager można zobaczyć zobaczyć tam jest hak, który demontuje zamknięcie procedur obsługi i zamyka je. Logger działa tylko w trybie wyłączenia, jeśli wcześniej nie był używany, więc ten kod nie jest uruchamiany.

// This private class is used as a shutdown hook. 
// It does a "reset" to close all open handlers. 
private class Cleaner extends Thread { 

    private Cleaner() { 
     /* Set context class loader to null in order to avoid 
     * keeping a strong reference to an application classloader. 
     */ 
     this.setContextClassLoader(null); 
    } 

    public void run() { 
     // This is to ensure the LogManager.<clinit> is completed 
     // before synchronized block. Otherwise deadlocks are possible. 
     LogManager mgr = manager; 

     // If the global handlers haven't been initialized yet, we 
     // don't want to initialize them just so we can close them! 
     synchronized (LogManager.this) { 
      // Note that death is imminent. 
      deathImminent = true; 
      initializedGlobalHandlers = true; 
     } 

     // Do a reset to close all active handlers. 
     reset(); 
    } 
} 


/** 
* Protected constructor. This is protected so that container applications 
* (such as J2EE containers) can subclass the object. It is non-public as 
* it is intended that there only be one LogManager object, whose value is 
* retrieved by calling Logmanager.getLogManager. 
*/ 
protected LogManager() { 
    // Add a shutdown hook to close the global handlers. 
    try { 
     Runtime.getRuntime().addShutdownHook(new Cleaner()); 
    } catch (IllegalStateException e) { 
     // If the VM is already shutting down, 
     // We do not need to register shutdownHook. 
    } 
} 

Z własnego testów

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      Logger logger2 = Logger.getLogger("Main2"); 
      logger2.info("Shutting down 2"); 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } 
    } 
})); 

drukuje

Dec 11, 2012 5:40:15 PM Main$1 run 
INFO: Shutting down 2 

ale jeśli dodać

Logger logger1 = Logger.getLogger("Main1"); 

poza tym bloku ty nic.

+1

Nawet przy użyciu Logger.getLogger (nazwa) nadal nie widzę niczego wydrukowanego w moim dzienniku. Jednak ustawiając właściwość System i kopiując kod MyLogManager, udało mi się go uruchomić.Pięknie dziękuję! – Marianna

1

Czy hak wyłączający ma jakąkolwiek przewagę?

Lepiej dodać wyjście dziennik w ostatniej linii w głównym: Blok finally zostaną wykonane we wszystkich przypadkach, z wyjątkiem gdy awarii VM ale wtedy hak zamykania będzie nie zostanie zrealizowane, zbyt.

static void main(String[] argv) { 

    try { 
    startApp(); 
    } finally { 
    LOGGER.info("shudown"); 
    } 
} 
+0

Mój proces to taki, który działa przez cały dzień - siedząc i czekając, aż coś się wydarzy. Nie jest to jedyna rzecz, która wystarczy, aby umieścić na końcu kodu to, czego potrzebuję. Wierzę, że hak zamykający to właściwe rozwiązanie. – Marianna

+1

Wygląda więc na to, że nie wiesz, gdzie kończy się twój kod? Powinieneś to wiedzieć i dowiedzieć się. To nie ma nic wspólnego z jednym strzałem! Nasz sw działa przez tygodnie bez wyłączania, ale wiemy, gdzie jest koniec. Może to trochę trudne, używając sprężyny lub innego frameworka. Ale powinieneś wiedzieć, żeby posprzątać, bo często konieczne jest uporządkowane zamknięcie! Powód, dla którego LOGGING potrzebuje obsługi przerwań, jest to, że jest to lib i nie może kojarzyć "końca kodu". – AlexWien

+0

Proces nie kończy się samoczynnie, więc podobnie nie ma logicznego końca. – Marianna

Powiązane problemy