我正在尝试在基于tomcat的Web应用程序中使用log4j2,所以我添加了log4j web模块以及其他必需的jar。但是,当停止此Web应用程序时,我得到以下异常。
FATAL Unable to register shutdown hook because JVM is shutting down
为什么我收到此错误以及如何防止此错误?
谢谢!
答案 0 :(得分:9)
正如Pouriya的回答所解释的那样,当你的应用程序在没有正确关闭挂钩的情况下停止时,你可能正在尝试使用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>
如果您使用普通应用程序,则需要明确添加关闭钩子:
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.");
}
});
}
应用程序结束时(即调用System.exit(0)
时会调用关闭挂钩。
您还需要在Log4J2配置文件中添加它:
XML版本:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration shutdownHook="disable">
...
</Configuration>
Json版本:
{"configuration":
{
"shutdownHook":"disable",
....
}
}
这将告诉Log4j2您正在自己处理Logger的关闭。
(因为在普通应用程序中,您没有web.xml文件,所以必须以其他方式检索配置文件。)
答案 1 :(得分:3)
如果在停止Web应用程序时遇到该错误,则表示您的挂钩尚未在正确的时间注册。根据定义,它应该在之前注册,以便在关闭期间实际调用它。
答案 2 :(得分:2)
该异常是由于在Apache Issues中的ID-LOG4J2-658下报告的错误导致的。上次我检查它是否仍然打开。
在此期间,要解决挑战,请在配置文件中添加 shutdownHook =“ disable” 作为添加的参数。这将禁用关机钩子
完整格式如下所示
<Configuration status="WARN" monitorInterval="30" shutdownHook="disable"> ... </Configuration>
关于如何使用关闭挂钩及其好处有很多解释。
但是它的简短版本是Shutdown Hooks是一个特殊的结构,允许开发人员插入要在JVM关闭时执行的一段代码。如果需要在VM关闭的情况下进行特殊清理操作,这将派上用场。
因此Log4J2试图使用shutdown钩子来正确关闭日志记录服务,但是由于该错误,它将引发异常。