Java -How to make the logger work at shutdown?

I have a specialized log class that uses the java.util.logging.Logger class. I want this logger to be able to use another class to shutdown. However, it does not appear to be logged on shutdown. From what I read, a shutdown hook can be activated for the recorder itself, which is causing the problem.

How can I make this work? Ideally, I would like this to be visible in the log file that I actually ran when the process terminated when the process terminated.

+6
source share
2 answers

Again, looking at the source, the solution seems to be defining the system property java.util.logging.manager , which is a subclass of LogManager that overrides the reset(); method reset(); so that the registrars continue to work at shutdown.

 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(); } } })); } } 

prints

 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 

From this code for LogManager, you can see that there is a disconnect hook that parses the handlers and closes them. Logger only works when shutting down, if it has not been used before, so this code does not run.

 // 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. } } 

From my own testing

 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(); } } })); 

prints

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

but if you add

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

outside this block you get nothing.

+8
source

Does the hook off have an advantage?

Better, add the log output to the last line in main: The finally block will be executed in all cases, except when the VM crashes, but then also fails.

 static void main(String[] argv) { try { startApp(); } finally { LOGGER.info("shudown"); } } 
+1
source

All Articles