java - log4j2 无法注册关闭 Hook ,因为 JVM 正在关闭

标签 java logging log4j apache-commons log4j2

我正在尝试在基于 tomcat 的 Web 应用程序中使用 log4j2,因此我添加了 log4j Web 模块以及其他必要的 jar。但是,当停止此 Web 应用程序时,出现以下异常。

FATAL Unable to register shutdown hook because JVM is shutting down

为什么我会收到此错误以及如何避免此错误?

谢谢!

最佳答案

正如 Pouriya 的回答中所解释的,当您的应用程序在没有适当的关闭 Hook 的情况下已经停止时,您可能正在尝试使用 Log4j2。 由于您在谈论 Tomcat Web 应用程序,因此我假设您使用的是 Servlet。 (如果不这样做,请参阅下面的第二部分)。然后,您必须在您的 ContextListener 中声明:

public class ContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent evt) {
        String appenderName = evt.getServletContext().getInitParameter("log4jContextName");
        File file = new File(evt.getServletContext().getInitParameter("log4jConfiguration"));
        if(!file.exists()){
            logger = LogManager.getRootLogger();
        } else{
            logger = LogManager.getLogger(appenderName);
        }
    }
}

@Override
public void contextDestroyed(ServletContextEvent evt) {
    // You don't really need to do anything here, about the logger.
    // The log4j2 JAR will handle it properly.
}

与 web 应用程序一样,Log4J2 的配置文件必须在 web.xml 文件中指明,如:

<?xml version="1.0" encoding="UTF-8"?>
<web-app ... >
    <context-param>
        <param-name>log4jContextName</param-name>
        <param-value>myApplication</param-value>
    </context-param>

    <context-param>
        <param-name>log4jConfiguration</param-name>
        <param-value>/the/path/to/your/log4j.properties.file</param-value>
    </context-param>
</web-app>

如果您使用的是普通应用程序,则需要显式添加关闭钩子(Hook):

public static void main( String[] args ) {

    ...

    File file = new File(logFileName);
    if(!file.exists()){
        logger = LogManager.getRootLogger();
    } else {
        System.setProperty("log4j.configurationFile", file.toURI().toURL().toString());
        logger = LogManager.getLogger("yourProgramName");
    }

    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            logger.info("Shutting down - closing application");
            // Shut down everything (e.g. threads) that you need to.

            // then shut down log4j
            if( LogManager.getContext() instanceof LoggerContext ) {
                logger.debug("Shutting down log4j2");
                Configurator.shutdown((LoggerContext)LogManager.getContext());
            } else
                logger.warn("Unable to shutdown log4j2");

            // logger not usable anymore
            System.out.println("Done.");
        }
    });
}

关闭 Hook 将在您的应用程序结束时调用(即调用 System.exit(0) 时。

您还需要在 Log4J2 配置文件中添加:

XML 版本:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration shutdownHook="disable">
...
</Configuration>

Json 版本:

{"configuration":
    {
        "shutdownHook":"disable",
        ....
    }
}

这将告诉 Log4j2 您正在自行处理 Logger 的关闭。

(因为在普通应用程序中您没有 web.xml 文件,您必须以其他方式检索您的配置文件)。

关于java - log4j2 无法注册关闭 Hook ,因为 JVM 正在关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30120330/

相关文章:

java - Android View 不响应绘图

java - 在将列表添加到 gridModel 之前对对象类列表进行排序

Python 日志记录 - DEBUG 下面有什么东西吗?

java - SonarQube:仅有条件地调用方法

log4j - 更改soapui-log4j.xml 后,SoapUI 不会更改日志文件名/路径

java - 使用 log4j 登录 Java Web Start

java - Android:尝试从其他类访问 TextView 时出现 NullPointerException

amazon-web-services - 如何获取 AWS CodeDeploy 日志并将其显示在 BitBucket 管道中

java - 将 log4j.properties 放入 Eclipse 中的 Maven 项目中,其中 "default package"文件夹内有一些 "src"?

java - 以编程方式从 Android 使用首选语言打开 Google Play