Java-如何使记录器在关闭挂钩中工作? [英] Java -How to get logger to work in shutdown hook?

查看:93
本文介绍了Java-如何使记录器在关闭挂钩中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个专门的记录器类,它使用java.util.logging.Logger类.我希望能够在另一个类的关闭钩子中使用此记录器.但是,它似乎并没有在关机时记录日志.根据我的阅读,可能已经为记录器本身激活了一个关闭挂钩,这导致了问题.

I have a specialized logger class which uses the java.util.logging.Logger class. I want to be able to use this logger in the shutdown hook of another class. However, it doesn't seem to log at shutdown. From what I've read, there may already be a shutdown hook activated for the logger itself which is causing the issue.

我该如何使用它?理想情况下,我希望在日志文件中看到实际上在进程终止时我执行了关机钩子.

How can I get this to work? Ideally, I would like it to be seen in the log file that I did in fact execute the shutdown hook when the process terminated.

推荐答案

再次查看源代码,解决方案似乎是定义一个系统属性java.util.logging.manager,该属性是LogManager的子类,它覆盖了reset();方法,因此记录仪将继续在关机状态下工作.

Again looking at the source, the solution appears to be to define a system property java.util.logging.manager which is a subclass of LogManager which overrides the reset(); method so the Loggers continue to work on 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();
                }
            }
        }));
    }
}

打印

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


从LogManager的此代码中,您可以看到有一个关闭钩子,该钩子可拆卸并关闭处理程序.如果Logger以前没有使用过,那么它只能在关机状态下工作,因此该代码不会运行.


From this code for LogManager, you can see see there is a shutdown hook which dismantles the handlers and closes them. Logger only works in shutdown if it hasn't been used before so this code is 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.
    }
}

根据我自己的测试

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

打印

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

但如果您添加

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

在此障碍物之外,您什么也没得到.

outside this block you get nothing.

这篇关于Java-如何使记录器在关闭挂钩中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆